Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android navigation component: how save fragment state

I use bottomNavigationView and navigation component. Please tell me how I don't destroy the fragment after switching to another tab and return to the old one? For example I have three tabs - A, B, C. My start tab is A. After I navigate to B, then return A. When I return to tab A, I do not want it to be re-created. How do it? Thanks

like image 772
Nikitc Avatar asked May 18 '19 03:05

Nikitc


People also ask

How do I save a fragment state?

Various Android system operations can affect the state of your fragment. To ensure the user's state is saved, the Android framework automatically saves and restores the fragments and the back stack. Therefore, you need to ensure that any data in your fragment is saved and restored as well.

How can we prevent fragment recreation in navigation component?

Just add the pop inclusive to all your action in nav graph. What the above pop behavior will do is, when you are navigating from, say C > B, it will pop everything till B (inclusive) from the back stack and add the latest instance of B on the back stack.

What is the use of addToBackStack in Android?

addToBackStack. Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.

Why is my Android fragment's state not saving?

Various Android system operations can affect the state of your fragment. To ensure the user's state is saved, the Android framework automatically saves and restores the fragments and the back stack. Therefore, you need to ensure that any data in your fragment is saved and restored as well.

Is there an API for a navigation fragment?

Even more unfortunately, Fragments do not offer an API for a system built on top of it (such as Navigation) to access the saved instance state and non configuration instance state (i.e., ViewModels) needed to write our own multiple back stack implementation while still using a single FragmentManager. With that in mind, we’ll be doing two things:

How to save&restore fragment state when switching tabs in Android?

The trick to it, is having the ability to save Fragment state when we switch the tab. Android does gave us ability to get the SavedState using saveFragmentInstanceState function as below. The above is cool. However, we have three tabs here (or possibly more), and we want a scalable way to save & restore the Fragment state.

How can I save the fragment state?

For the fragment state to be saved properly, we need to be sure that we aren't unnecessarily recreating the fragment on configuration changes. This means being careful not to reinitialize existing fragments when they already exist. Any fragments being initialized in an Activity need to be looked up by tag after a configuration change:


3 Answers

As per the open issue, Navigation does not directly support multiple back stacks - i.e., saving the state of stack B when you go back to B from A or C since Fragments do not support multiple back stacks.

As per this comment:

The NavigationAdvancedSample is now available at https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample

This sample uses multiple NavHostFragments, one for each bottom navigation tab, to work around the current limitations of the Fragment API in supporting multiple back stacks.

We'll be proceeding with the Fragment API to support multiple back stacks and the Navigation API to plug into it once created, which will remove the need for anything like the NavigationExtensions.kt file. We'll continue to use this issue to track that work.

Therefore you can use the NavigationAdvancedSample approach in your app right now and star the issue so that you get updates for when the underlying issue is resolved and direct support is added to Navigation.

like image 200
ianhanniballake Avatar answered Oct 08 '22 23:10

ianhanniballake


In case you can deal with destroying fragment, but want to save ViewModel, you can scope it into the Navigation Graph:

private val viewModel: FavouritesViewModel by 
    navGraphViewModels(R.id.mobile_navigation) {
        viewModelFactory
    }

Read more here

EDIT

As @SpiralDev noted, using Hilt simplifies a bit:

private val viewModel: MainViewModel by 
    navGraphViewModels(R.id.mobile_navigation) {
         defaultViewModelProviderFactory     
    }
like image 40
Dievskiy Avatar answered Oct 09 '22 01:10

Dievskiy


just use navigation component version 2.4.0-alpha01 or above

like image 5
Herlian Zhang Avatar answered Oct 08 '22 23:10

Herlian Zhang