直接贴出报错内容:java.lang.IllegalArgumentException
D/ATestFragment:java.lang.IllegalArgumentException:
Navigation action/destination(id/action_aTestFragment_to_bTestFragment) cannot be found from the current destination Destination(id/testDialogFragment) label=TestDialogFragment
报错内容理解为:从当前的 destination(DislogFragment)找不到 Navigation action [从 ATestFragment 导航(跳转)到 BTestFragment]。
一个跳转怎么会找不到呢,这里继续贴上关键代码:
在DislogFragment 执行方法:
private fun savedStateHandleResult(type: ConnectivityType) {
val navController = findNavController()
with(navController) {
dismiss()
previousBackStackEntry?.savedStateHandle?.set(RESULT, type)
}
}
然后在ATestFragment监听 savedStateHandle 值,然后跳转至BTestFragment:
private fun addConnectivitySavedStateHandleCallback() {
val savedStateHandle = findNavController().currentBackStackEntry?.savedStateHandle
val result =
savedStateHandle?.getLiveData<ConnectivityType>(RESULT)
result?.observe(viewLifecycleOwner, {
when (it) {
ConnectivityType.PROMPT_TYPE_NETWORK_CONNECTED -> {
savedStateHandle?.remove<ConnectivityType>(RESULT)
findNavController().navigate(R.id.action_aTestFragment_to_bTestFragment)
}
}
})
}
这看起来没有问题,运行起来就会报错(开头已贴出来),根据报错,可以知道在调用完 dismiss() , 然后给 previousBackStackEntry?.savedStateHandle 赋值,ATestFragment 也监听到 savedStateHandle 值,然后也执行了导航至BTestFragment 的方法, 但这时候提示当前的 destination 仍然为DislogFragment,还是有点奇怪的。不过既然这样写法不行,我想着换成 popBackStack(), 如下:
private fun savedStateHandleResult(type: ConnectivityType) {
val navController = findNavController()
with(navController) {
popBackStack()
previousBackStackEntry?.savedStateHandle?.set(RESULT, type)
}
}
这样却发现 ATestFragment 监听不到 savedStateHandle 值,这就奇怪了,然后就去查原因,各种调试,看源码;过程很苦逼哈!
最后我也整理了一篇文章来说明(欢迎查看):
Navigation: DialogFragment popBackStack() 和 dismiss() 比较currentBackStackEntry/previousBackStackEntry
然后会豁然开朗,原因是dismiss和popBackStack执行后是有区别的:(截取上篇文章中的片段)
对于一个有延迟性(dismiss),一个是及时性(popBackStack),所以解决方式呼之欲出:
private fun savedStateHandleResult(type: ConnectivityType) {
val navController = findNavController()
with(navController) {
popBackStack()
// 将“ previousBackStackEntry”替换为“ currentBackStackEntry”:
// 用于从DialogFragment返回到Fragment后直接导航到新的Fragment。
// 它将包含与目标相对应的DialogFragment,并且不会在backStack中及时清除,
// 并且将报告:IllegalArgumentException:无法从当前目标位置找到导航操作/目标。
currentBackStackEntry?.savedStateHandle?.set(RESULT, type)
}
}