问题
Currently, I am playing around Android Navigation Component with Bottom Navigation Bar. While playing I realized two facts:
- Fragments are always recreated (
onCreate
,onViewCreated
,onViewDestroyed
are called as soon as the user navigates to another fragment) savedInstanceState
is always null (inonCreate
,onViewCreated
, etc.)
The first issue can be fixed by using custom FragmentNavigator
, which will reuse fragment if it already exists
package am.chamich.apps.advancedbottomnavigation.navigator
import android.content.Context
import android.os.Bundle
import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.fragment.FragmentNavigator
@Navigator.Name("retain_state_fragment")
class RetainStateFragmentNavigator(
private val context: Context,
private val manager: androidx.fragment.app.FragmentManager,
private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {
override fun navigate(
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Navigator.Extras?
): NavDestination? {
val tag = destination.id.toString()
val transaction = manager.beginTransaction()
val currentFragment = manager.primaryNavigationFragment
if (currentFragment != null) {
transaction.detach(currentFragment)
}
var fragment = manager.findFragmentByTag(tag)
if (fragment == null) {
val className = destination.className
fragment = instantiateFragment(context, manager, className, args)
transaction.add(containerId, fragment, tag)
} else {
transaction.attach(fragment)
}
transaction.setPrimaryNavigationFragment(fragment)
transaction.setReorderingAllowed(true)
transaction.commit()
return destination
}
}
Question
For the second issue, I have no idea how to fix it, actually, I even didn't understand how the fragment is restoring its state (for example when you rotate the screen), I tied to use fragment.setInitialSavedState(savedState)
to save and restore fragment state, but that doesn't help in this situation.
Actually what I need to know is when fragment view was recreated
Here is a link to my GitHub project, any help is welcome.
回答1:
Check this Blog, http://www.androiddevelopment.co.in/2019/05/how-to-save-android-activity-state.html, This Blog explain how to save activity state when the activity is destroyed.
For example, If you change the language of your phone while the activity was running (and so different resources from your project need to be loaded). Another very common scenario is when you rotate your phone to the side so that the activity is recreated and displayed in landscape. You can use this technique to store instance values for your application (selections, unsaved text, etc.).
回答2:
Fragment will save its state only when activity is recreated (e.g. screen rotation) and changing the fragment doesn't matter. From documentation:
There are many situations where a fragment may be mostly torn down (such as when placed on the back stack with no UI showing), but its state will not be saved until its owning activity actually needs to save its state.
Source
Saving custom state:
Put this method inside fragment:
override fun onSaveInstanceState(outState: Bundle) {
outState.putString("text", "some value")
super.onSaveInstanceState(outState)
}
And read the value, for example, inside onViewCreated
:
val text = savedInstanceState?.getString("text")
You will receive desired value after screen rotation / phone language change or other config changes - when activity (and fragment) is being recreated.
来源:https://stackoverflow.com/questions/55801039/fragment-savedinstancestate-is-always-null-when-using-navigation-component