Android 在重新创建活动后以编程方式设置导航图时,会显示错误的片段
我正在以编程方式设置一个导航图,以根据某些条件(例如,活动会话)设置开始目标,但是当我在启用“不保持活动”选项的情况下进行测试时,我遇到了以下错误 当刚刚重新创建活动并且应用程序调用方法NavController.setGraph时,NavController强制恢复导航回堆栈(从内部字段mBackStackToRestore in onGraphCreated方法),即使开始目标与以前不同,用户也会看到错误的片段 这是我的主要活动代码: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
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中设置开始目标时,收到一个异常。问题在于,在重新创建活动之后,不会重新创建导航图,而是创建片段。此外,在不重新创建图形的情况下更改起始目标也不会产生任何影响:(