重新创建 activity 后以编程方式设置导航图时,显示错误的片段
When setting navigation graph programmatically after recreating activity, wrong fragment is shown
-
android
-
android-navigation
-
android-jetpack
-
android-architecture-navigation
-
android-jetpack-navigation
我正在以编程方式设置导航图,以根据某些条件(例如,活动会话)设置起始目的地,但是当我在启用“不保留活动”选项的情况下对此进行测试时,我遇到了以下错误.
当 activity 刚刚重新创建并且应用程序调用方法 NavController.setGraph 时,NavController 强制恢复导航返回堆栈(从 onGraphCreated 方法中的内部字段 mBackStackToRestore),即使起始目的地与之前不同所以用户看到了错误的片段。
这是我的 MainActivity 代码:
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
}
}
片段一和片段二只是空片段。
它的样子:
包含完整代码和更多解释的存储库 link
我的问题:是导航库错误还是我做错了什么?也许我使用的方法不好,有更好的方法可以实现我想要的?
正如您在存储库中尝试的那样,它来自 save/restoreInstanceState。
这意味着您通过 createGraph(App.instance.getValue())
在 onCreate
中设置了 suit graph,然后 onRestoreInstanceState
中的 fragmentManager 将覆盖您对 NavHostFragment 的配置。
因此您可以将onRestoreInstanceState
中的图表设置为另一个时间。但它不会工作,因为 this line 并且 backstack 不为空。 (我认为这种行为可能是一个错误...)
因为你在不同的情况下使用图表 (R.navigation.nav_graph)
并且只是改变他们的 startDestination
,你可以确定在进程死亡后,使用的图表是你的需求图表。所以只需在 onRestoreInstanceState
.
中覆盖 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% 正确。至少,有更好的,而且效果很好。
因为我使用的是相同的图表并且只更改了起始目的地,所以我可以简单地在 activity 的 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)
android
android-navigation
android-jetpack
android-architecture-navigation
android-jetpack-navigation
我正在以编程方式设置导航图,以根据某些条件(例如,活动会话)设置起始目的地,但是当我在启用“不保留活动”选项的情况下对此进行测试时,我遇到了以下错误.
当 activity 刚刚重新创建并且应用程序调用方法 NavController.setGraph 时,NavController 强制恢复导航返回堆栈(从 onGraphCreated 方法中的内部字段 mBackStackToRestore),即使起始目的地与之前不同所以用户看到了错误的片段。
这是我的 MainActivity 代码:
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
}
}
片段一和片段二只是空片段。
它的样子:
包含完整代码和更多解释的存储库 link
我的问题:是导航库错误还是我做错了什么?也许我使用的方法不好,有更好的方法可以实现我想要的?
正如您在存储库中尝试的那样,它来自 save/restoreInstanceState。
这意味着您通过 createGraph(App.instance.getValue())
在 onCreate
中设置了 suit graph,然后 onRestoreInstanceState
中的 fragmentManager 将覆盖您对 NavHostFragment 的配置。
因此您可以将onRestoreInstanceState
中的图表设置为另一个时间。但它不会工作,因为 this line 并且 backstack 不为空。 (我认为这种行为可能是一个错误...)
因为你在不同的情况下使用图表 (R.navigation.nav_graph)
并且只是改变他们的 startDestination
,你可以确定在进程死亡后,使用的图表是你的需求图表。所以只需在 onRestoreInstanceState
.
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% 正确。至少,有更好的,而且效果很好。
因为我使用的是相同的图表并且只更改了起始目的地,所以我可以简单地在 activity 的 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)