Android 在重新创建活动后以编程方式设置导航图时,会显示错误的片段

Android 在重新创建活动后以编程方式设置导航图时,会显示错误的片段,android,android-jetpack,android-architecture-navigation,android-navigation,android-jetpack-navigation,Android,Android Jetpack,Android Architecture Navigation,Android Navigation,Android Jetpack Navigation,我正在以编程方式设置一个导航图,以根据某些条件(例如,活动会话)设置开始目标,但是当我在启用“不保持活动”选项的情况下进行测试时,我遇到了以下错误 当刚刚重新创建活动并且应用程序调用方法NavController.setGraph时,NavController强制恢复导航回堆栈(从内部字段mBackStackToRestore in onGraphCreated方法),即使开始目标与以前不同,用户也会看到错误的片段 这是我的主要活动代码: class MainActivity : AppComp

我正在以编程方式设置一个导航图,以根据某些条件(例如,活动会话)设置开始目标,但是当我在启用“不保持活动”选项的情况下进行测试时,我遇到了以下错误

当刚刚重新创建活动并且应用程序调用方法NavController.setGraph时,NavController强制恢复导航回堆栈(从内部字段mBackStackToRestore in onGraphCreated方法),即使开始目标与以前不同,用户也会看到错误的片段

这是我的主要活动代码:

class MainActivity : AppCompatActivity() {

    lateinit var navController: NavController
    lateinit var navHost: NavHostFragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        log("fresh start = ${savedInstanceState == null}")
        navHost = supportFragmentManager.findFragmentById(R.id.main_nav_host) as NavHostFragment
        navController = navHost.navController
        createGraph(App.instance.getValue())
    }

    private fun createGraph(bool: Boolean) {
        Toast.makeText(this, "Is session active: $bool", Toast.LENGTH_SHORT).show()
        log("one: ${R.id.fragment_one}, two: ${R.id.fragment_two}")
        val graph =
            if (bool) {
                log("fragment one")
                navController.navInflater.inflate(R.navigation.nav_graph).also {
                    it.startDestination = R.id.fragment_one
                }
            } else {
                log("fragment two")
                navController.navInflater.inflate(R.navigation.nav_graph).also {
                    it.startDestination = R.id.fragment_two
                }
            }
        navController.setGraph(graph, null)
    }
}
应用程序代码:

class App : Application() {
    companion object {
        lateinit var instance: App
    }

    private var someValue = true
    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    fun getValue(): Boolean {
        val result = someValue
        someValue = !someValue
        return result
    }
}
片段1和片段2只是空片段

它看起来是什么样子:

提供完整代码和更多解释的存储库


我的问题:这是导航库错误还是我做错了什么?也许我使用了一种不好的方法,但有一种更好的方法来实现我想要的吗?

当您在存储库中尝试时,它来自save/restoreInstanceState

这意味着您可以通过
createGraph(App.instance.getValue())
onCreate
中设置套装图,然后
onRestoreInstanceState
中的fragmentManager将覆盖您对NavHostFragment的配置

因此,您可以在
onRestoreInstanceState
中设置图形的另一个时间。但它不会起作用,因为backback不是空的。(我认为这种行为可能是一个bug…)

由于您使用的是一个图形
(R.navigation.nav_graph)
,用于不同的情况,只需更改它们的
起始目标
,因此您可以确保在进程终止后,使用的图形就是您的需求图。因此,只需在恢复安装状态中覆盖
startDestination

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    if (codition) {
        navController.graph.startDestination = R.id.fragment_one
    } else {
        navController.graph.startDestination = R.id.fragment_two
    }
}

看起来图书馆里有一些错误的行为,我的方法也不是100%正确。至少,有一个更好的,而且效果很好。 因为我使用的是同一个图,并且只更改了开始目标,所以我可以在活动的onCreate中简单地设置该图,并在那里设置一些默认的开始目标。然后,在
createGraph
方法中,我可以执行以下操作:

    // pop backStack while it is not empty
    while (navController.currentBackStackEntry != null) {
        navController.popBackStack()
    }
    // then just navigate to desired destination with additional arguments if needed
    navController.navigate(destinationId, destinationBundle)

谢谢你的回答!当我试图在onRestoreInstanceState中设置开始目标时,收到一个异常。问题在于,在重新创建活动之后,不会重新创建导航图,而是创建片段。此外,在不重新创建图形的情况下更改起始目标也不会产生任何影响:(