如何修复Android使用Navigation跳转时无法从当前目的地找到目标的错误
错误成因
- 核心原因是Dialog销毁和导航操作的执行时机冲突:你在点击按钮时同时调用了
navigate()和dismiss(),Dialog销毁的过程中导航控制器的当前目的地已经被回退到上一级(也就是write页面),此时再调用只有bodyPartDialog目的地才有的action_bodyPartDialog_to_write跳转,当前目的地不匹配,自然找不到对应action。 - 额外问题:你的跳转逻辑本身冗余,Dialog本来就是从
write页面打开的,关闭后默认就会回到write页面,额外调用跳转反而会在回退栈中多压入一个新的write实例,不符合回传数据的需求。
解决方案
方案1:使用官方回传数据接口(推荐)
无需跳转回write页面,直接用Navigation提供的SavedStateHandle回传数据即可,步骤如下:
- 删除nav_graph中
bodyPartDialog下冗余的action_bodyPartDialog_to_write配置。 - 调整DialogFragment的点击逻辑,直接向上一级页面回传参数:
startBtn?.setOnClickListener { v -> title = BodyPartCustomView.getTitle() // 向上一个回退栈条目存入数据,key可自定义 findNavController().previousBackStackEntry?.savedStateHandle?.set("bodyPartTitle", title) dismiss() }
- 在
WritingRoutineFragment的onViewCreated方法中监听回传的参数:
navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("bodyPartTitle")?.observe(viewLifecycleOwner) { title -> // 此处处理拿到的回传参数 // 处理完成后移除数据,避免下次回到页面重复触发 navController.currentBackStackEntry?.savedStateHandle?.remove<String>("bodyPartTitle") }
方案2:保留跳转逻辑的修复方式
如果确实需要保留跳转配置,需要先判断当前目的地是否匹配,避免时机冲突导致的报错:
- 先给跳转action添加弹出配置,避免回退栈出现重复的
write实例:
<action android:id="@+id/action_bodyPartDialog_to_write" app:destination="@id/write" app:popUpTo="@id/write" app:popUpToInclusive="true" />
- 调整DialogFragment的跳转逻辑,增加当前目的地校验:
startBtn?.setOnClickListener { v -> title = BodyPartCustomView.getTitle() val navController = findNavController() // 校验当前目的地是bodyPartDialog时再执行跳转 if (navController.currentDestination?.id == R.id.bodyPartDialog) { val action = BodyPartDialogFragmentDirections.actionBodyPartDialogToWrite(title) navController.navigate(action) dismiss() } }
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

