Reputation: 322
My current version of navigation is:
implementation("androidx.navigation:navigation-fragment-ktx:2.8.0")
implementation("androidx.navigation:navigation-ui-ktx:2.8.0")
Inside a fragment I have a FragmentContainerView
and BottomNavigationView
. I set them up using navController
like so:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navView: BottomNavigationView = binding.bottomNav
val navHostFragment = (childFragmentManager.findFragmentById(
R.id.navHostFragment
) as NavHostFragment)
navView.setupWithNavController(navController)
}
Whenever I navigate through tabs (e.g. home -> profile -> home) the ProfileViewModel
is saved (meaning its onCleared
is not called). But if I press back button when profile tab is selected, the ProfileViewModel
's onCleared
is being called.
I even tried to add OnBackPressedCallback
to override any back press but its handleOnBackPressed
is not being called:
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, onBackPressedCallback)
How can I make the navController
to stop clearing the view model when back button is pressed?
Upvotes: 0
Views: 58
Reputation: 30985
EDIT: I did not read your question carefully enough.
You are experiencing the effects of the new "multiple back stack" support in the navigation library.
https://developer.android.com/guide/navigation/backstack/multi-back-stacks
When you press the Home tab from the Profile screen, you are actually switching back stacks under the hood. Because Profile screen is still in the back stack for the Profile tab, it's view model store is still active and the view model is not cleared.
When you press Back from the Profile screen, you are popping the back stack. This destroys the fragment, which clears its view model store, along with the view model.
This behavior is all by design.
I am currently in the process of integrating Navigation component into my app, and let me say: you are not the only one struggling to get "expected" behavior out of their app.
You can try turning off back stack save state and see if the behavior works better for your case:
Refer to https://developer.android.com/topic/libraries/architecture/viewmodel/viewmodel-apis
Having the ViewModel cleared is generally a good thing; usually you want to make sure the ViewModel is not displaying stale data in the UI.
But if you really really want that ViewModel to retain data while you navigate around, a simple way is to scope the ViewModel to the Activity:
val viewModel: SharedViewModel by activityViewModels()
Both the Fragment and Activity have ViewModel stores, by using the Activity's you can keep the ViewModel from clearing while you navigate to a different fragment.
Upvotes: 1