navigation.xml
android:id=
"@+id/mobile_navigation"
app:startDestination=
"@+id/navigation_home"
>
<fragment
android:id=
"@+id/navigation_home"
android:name=
"com.krpot.android.navigationdemo.ui.home.HomeFragment"
android:label=
"@string/title_home"
tools:layout=
"@layout/fragment_home"
/>
<fragment
android:id=
"@+id/nav_login"
android:name=
"com.krpot.android.navigationdemo.ui.login.LoginFragment"
android:label=
"@string/title_login"
tools:layout=
"@layout/fragment_login"
/>
</navigation>
class
HomeFragment : Fragment(R.layout.fragment_home) {
private
lateinit var homeViewModel: HomeViewModel
private
var _binding: FragmentHomeBinding? =
null
private
val binding get() = _binding!!
override fun onDestroyView() {
super
.onDestroyView()
_binding =
null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super
.onViewCreated(view, savedInstanceState)
setupViews()
handleLoginForm()
}
private
fun setupViews() {
_binding = FragmentHomeBinding.bind(requireView())
binding.apply {
logoutBtn.setOnClickListener {
findNavController().navigate(R.id.nav_login)
}
}
}
private
fun handleLoginForm() {
val navController = findNavController()
val navBackStackEntry = navController.getBackStackEntry(R.id.navigation_home)
val observer = LifecycleEventObserver { _, event ->
if
(event == Lifecycle.Event.ON_RESUME
&& navBackStackEntry.savedStateHandle.contains(LoginFragment.EXTRA_RESULT_KEY)
) {
val loginResult =
navBackStackEntry.savedStateHandle.get<LoginInfo>(LoginFragment.EXTRA_RESULT_KEY);
showLoginResult(loginResult!!)
}
}
navBackStackEntry.lifecycle.addObserver(observer)
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if
(event == Lifecycle.Event.ON_DESTROY) {
navBackStackEntry.lifecycle.removeObserver(observer)
}
})
}
private
fun showLoginResult(loginResult: LoginInfo) {
Toast.makeText(requireContext(),
"login successful!!!($loginResult)"
, Toast.LENGTH_SHORT).show()
}
}
class
LoginFragment : Fragment(R.layout.fragment_login) {
companion object {
const
val EXTRA_RESULT_KEY =
"Extra.Result"
}
private
val viewModel: LoginViewModel by lazy { ViewModelProvider(
this
).get(LoginViewModel::
class
.java) }
private
var _binding: FragmentLoginBinding? =
null
private
val binding get() = _binding!!
override fun onDestroyView() {
super
.onDestroyView()
_binding =
null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super
.onViewCreated(view, savedInstanceState)
setupViews()
}
private
fun setupViews() {
_binding = FragmentLoginBinding.bind(requireView())
binding.apply {
loginBtn.setOnClickListener {
viewModel.submitLogin(userNameTxt.text.toString(), passwordTxt.text.toString())
}
}
viewModel.loginInfo.observe(viewLifecycleOwner, Observer { loginInfo ->
val navController = findNavController()
navController.previousBackStackEntry?.savedStateHandle?.set(EXTRA_RESULT_KEY, loginInfo)
navController.popBackStack()
})
}
}
class
LoginViewModel : ViewModel() {
private
val _loginInfo = MutableLiveData<LoginInfo>()
val loginInfo: LiveData<LoginInfo> = _loginInfo
fun submitLogin(userName: String, password: String) {
val loginInfo = LoginInfo(userName, password)
viewModelScope.launch {
val loginResult = handleLogin(loginInfo)
_loginInfo.postValue(loginResult)
}
}
private
suspend fun handleLogin(loginInfo: LoginInfo): LoginInfo {
delay(1000L)
return
loginInfo
}
}
data
class
LoginInfo(
val userName: String,
val password: String
) : Serializable