使用 androidx.navigation 时随机崩溃
Random crashes when using androidx.navigation
使用时
'androidx.navigation:navigation-ui-ktx:2.3.0'
'androidx.navigation:navigation-fragment-ktx:2.3.0'
该应用程序正常运行了一段时间,直到我开始随机获取
Navigation action/destination cannot be found from the current destination NavGraph
当我点击任何触发导航的按钮时,我使用这样的导航
//to navigate
var dir = MainMenuDirections.actionMainMenuToSelectPayments()
NavHostFragment.findNavController(this).navigate(dir)
//to pop current fragment
NavHostFragment.findNavController(this).popBackStack()
我试过使用 2.2.0 版
显然这是自版本 1.0.0 alpha 4 以来存在的错误,当您在调用 popBackStack() 之后调用 Navigate() 时会发生这种情况,很奇怪每个人是如何使用它的?
如果有人犯了我犯的错误,我会从问题跟踪器得到答案
这与 b/128734685 类似,其中 nav.popBackStack()
返回 false 意味着仍然从后台堆栈中删除您的 login2。
这就是错误消息显示的原因:
java.lang.IllegalArgumentException: Navigation action/destination com.dzdoes.i.payments:id/action_login2_to_registre cannot be found from the current destination NavGraph(com.dzdoes.i.payments:id/nav_graph) startDestination={Destination(com.dzdoes.i.payments:id/login2) label=Login class=com.dzdoes.i.payments.ui.Auth.Login}
Correctly indicating that you are not on the login2 destination (you are on the root nav_graph, which correctly does not have an action named action_login2_to_registre).
这是预期的行为,正如在另一个问题中提到的,您仍然在屏幕上看到片段的唯一原因是允许 activity 动画完成且片段仍然可见(而不是动画一个空 activity).
你有两个选择:
停止覆盖 onBackPressed()
。相反,您应该遵循提供的自定义后退导航,并在 activity 级别注册您自己的 OnBackPressedCallback
回调,没有 LifecycleOwner
。这将确保它仅在没有导航返回堆栈时触发:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val builder: AlertDialog.Builder = AlertDialog.Builder(this@NavHostAuth)
builder
.setMessage("are you sure you want to exit")
.setPositiveButton("yes") { _, _ -> finish() }
.setNegativeButton("no") { _, _ -> }
.show()
}
})
}
请注意,您需要将 app:defaultNavHost="true"
添加到 XML,因为这是导致 NavHostFragment
默认正确拦截后退按钮的原因。这是实现此功能的推荐方法。
更新您的 setNegativeButton
以再次导航到您的起始目的地。
.setNegativeButton(
"no",
DialogInterface.OnClickListener { dialog, which -> nav.navigate(R.id.login2) })
请注意,在任何一种情况下,您都不需要从 setNegativeButton
侦听器调用 dialog.dismiss()
- 只要按下肯定或否定按钮,AlertDialog
就会自动消失.
使用时
'androidx.navigation:navigation-ui-ktx:2.3.0'
'androidx.navigation:navigation-fragment-ktx:2.3.0'
该应用程序正常运行了一段时间,直到我开始随机获取
Navigation action/destination cannot be found from the current destination NavGraph
当我点击任何触发导航的按钮时,我使用这样的导航
//to navigate
var dir = MainMenuDirections.actionMainMenuToSelectPayments()
NavHostFragment.findNavController(this).navigate(dir)
//to pop current fragment
NavHostFragment.findNavController(this).popBackStack()
我试过使用 2.2.0 版
显然这是自版本 1.0.0 alpha 4 以来存在的错误,当您在调用 popBackStack() 之后调用 Navigate() 时会发生这种情况,很奇怪每个人是如何使用它的?
如果有人犯了我犯的错误,我会从问题跟踪器得到答案
这与 b/128734685 类似,其中 nav.popBackStack()
返回 false 意味着仍然从后台堆栈中删除您的 login2。
这就是错误消息显示的原因:
java.lang.IllegalArgumentException: Navigation action/destination com.dzdoes.i.payments:id/action_login2_to_registre cannot be found from the current destination NavGraph(com.dzdoes.i.payments:id/nav_graph) startDestination={Destination(com.dzdoes.i.payments:id/login2) label=Login class=com.dzdoes.i.payments.ui.Auth.Login}
Correctly indicating that you are not on the login2 destination (you are on the root nav_graph, which correctly does not have an action named action_login2_to_registre).
这是预期的行为,正如在另一个问题中提到的,您仍然在屏幕上看到片段的唯一原因是允许 activity 动画完成且片段仍然可见(而不是动画一个空 activity).
你有两个选择:
停止覆盖 onBackPressed()
。相反,您应该遵循提供的自定义后退导航,并在 activity 级别注册您自己的 OnBackPressedCallback
回调,没有 LifecycleOwner
。这将确保它仅在没有导航返回堆栈时触发:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val builder: AlertDialog.Builder = AlertDialog.Builder(this@NavHostAuth)
builder
.setMessage("are you sure you want to exit")
.setPositiveButton("yes") { _, _ -> finish() }
.setNegativeButton("no") { _, _ -> }
.show()
}
})
}
请注意,您需要将 app:defaultNavHost="true"
添加到 XML,因为这是导致 NavHostFragment
默认正确拦截后退按钮的原因。这是实现此功能的推荐方法。
更新您的 setNegativeButton
以再次导航到您的起始目的地。
.setNegativeButton(
"no",
DialogInterface.OnClickListener { dialog, which -> nav.navigate(R.id.login2) })
请注意,在任何一种情况下,您都不需要从 setNegativeButton
侦听器调用 dialog.dismiss()
- 只要按下肯定或否定按钮,AlertDialog
就会自动消失.