使用导航组件时,片段 savedInstanceState 始终为空
Posted
技术标签:
【中文标题】使用导航组件时,片段 savedInstanceState 始终为空【英文标题】:Fragment savedInstanceState is always null when using Navigation Component 【发布时间】:2019-09-12 00:55:07 【问题描述】:目前,我正在玩带有底部导航栏的 android 导航组件。在玩的过程中,我意识到两个事实:
片段总是被重新创建(onCreate
、onViewCreated
、onViewDestroyed
在用户导航到另一个片段时被调用)
savedInstanceState
始终为 null(在 onCreate
、onViewCreated
等中)
第一个问题可以通过使用自定义FragmentNavigator
来解决,如果片段已经存在,它将重用片段
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
问题
对于第二个问题,我不知道如何解决它,实际上,我什至不明白片段是如何恢复其状态的(例如当你旋转屏幕时),我绑定使用fragment.setInitialSavedState(savedState)
保存和恢复片段状态,但这在这种情况下无济于事。
其实我需要知道的是何时重新创建片段视图
这是我的 GitHub 项目的link,欢迎提供任何帮助。
【问题讨论】:
你可以在这里查看片段的生命周期developer.android.com/guide/components/fragments @ErginErsoy 我知道片段的生命周期,但这无助于解决问题,问题是 saveInstanceState 始终为空,即使重新附加片段也是如此 你检查过这个问题的答案吗***.com/questions/20550016/… @ErginErsoy 是的,我检查过,我什至尝试过。根本不工作:( @ErginErsoy 您可以查看我的项目并尝试运行它,单击导航项时会出现大量日志,您将在日志中看到saveinstance
状态始终为 null : (
【参考方案1】:
Fragment 只有在重新创建 Activity(例如屏幕旋转)时才会保存其状态,并且更改 Fragment 并不重要。来自文档:
在很多情况下,一个片段可能大部分被拆除(例如当放置在没有显示 UI 的后堆栈上时),但它的状态不会被保存,直到它拥有的 Activity 实际需要保存它的状态。
Source
保存自定义状态:
将此方法放入片段中:
override fun onSaveInstanceState(outState: Bundle)
outState.putString("text", "some value")
super.onSaveInstanceState(outState)
并读取值,例如onViewCreated
内部:
val text = savedInstanceState?.getString("text")
在屏幕旋转/手机语言更改或其他配置更改后 - 当重新创建活动(和片段)时,您将收到所需的值。
【讨论】:
【参考方案2】:查看这个博客,http://www.androiddevelopment.co.in/2019/05/how-to-save-android-activity-state.html,这个博客解释了如何在活动被销毁时保存活动状态。
例如,如果您在 Activity 运行时更改了手机的语言(因此需要加载项目中的不同资源)。另一个非常常见的场景是当您将手机旋转到一边,以便重新创建活动并以横向显示。您可以使用此技术为您的应用程序存储实例值(选择、未保存的文本等)。
【讨论】:
以上是关于使用导航组件时,片段 savedInstanceState 始终为空的主要内容,如果未能解决你的问题,请参考以下文章
导航组件 - BottomNavigationView - 返回时不要保留 startDestination 片段