使用导航组件时,片段savedInstanceState始终为null [英] Fragment savedInstanceState is always null when using Navigation Component

本文介绍了使用导航组件时,片段savedInstanceState始终为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在使用带有底部导航栏的Android导航组件.在玩游戏时,我意识到了两个事实:

Currently, I am playing around Android Navigation Component with Bottom Navigation Bar. While playing I realized two facts:

  • 总是重新创建片段(一旦用户导航到另一个片段,就会调用onCreateonViewCreatedonViewDestroyed)
  • savedInstanceState始终为空(在onCreateonViewCreated等中)
  • Fragments are always recreated (onCreate, onViewCreated, onViewDestroyed are called as soon as the user navigates to another fragment)
  • savedInstanceState is always null (in onCreate, onViewCreated, etc.)

可以通过使用自定义FragmentNavigator修复第一个问题,该自定义FragmentNavigator将重用碎片(如果已经存在)

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
    }
}

问题

对于第二个问题,我不知道如何解决它,实际上,我什至不了解该片段如何恢复其状态(例如,当您旋转屏幕时),我不得不使用fragment.setInitialSavedState(savedState)保存并恢复片段状态,但这在这种情况下无济于事.

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.

实际上我需要知道的是何时重新创建片段视图

这里是我的GitHub项目的链接,欢迎任何帮助.

Here is a link to my GitHub project, any help is welcome.

推荐答案

仅当重新创建活动(例如屏幕旋转)并且更改片段无关紧要时,片段才会保存其状态.从文档中:

Fragment will save its state only when activity is recreated (e.g. screen rotation) and changing the fragment doesn't matter. From documentation:

在很多情况下,片段可能大部分都被撕裂(例如,当放置在没有显示UI的后堆栈上),但是直到其拥有的活动真正需要保存其状态时,它的状态才会被保存.

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.

来源

保存自定义状态:

将此方法放在片段中:

override fun onSaveInstanceState(outState: Bundle) {
    outState.putString("text", "some value")
    super.onSaveInstanceState(outState)
}

并读取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.

这篇关于使用导航组件时,片段savedInstanceState始终为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆