嵌套Fragment调用Navigation组件导航找不到目标报错如何解决
报错核心是拿错了NavController实例。
你在FragmentContainerView承载的嵌套CameraDetailsFragment里直接调用navigate()时,默认通过findNavController()拿到的是当前Fragment视图层级最近绑定的控制器,但这个静态加载的嵌套Fragment没有绑定外层导航图的NavHost,控制器持有的导航栈、目的地信息和外层导航图完全不匹配,自然找不到对应的action/destination。
而你在承载FragmentContainerView的宿主Fragment里调用导航逻辑时,拿到的是外层NavHost绑定的正确控制器,匹配对应导航图,所以能正常运行。
二选一即可,优先选方案1,改造成本最低。
方案1:手动获取宿主Fragment绑定的正确NavController
不要在嵌套Fragment里直接调用自身的findNavController(),改为通过父Fragment拿外层绑定的NavController执行导航,替换原有导航代码:
override fun onEditPressed() { // 顺着父Fragment拿到绑定了外层导航图的NavController val correctNavController = requireParentFragment().findNavController() correctNavController.navigate( CameraDetailsFragmentDirections.actionCameraDetailsFragmentToAddCameraFragment(model = currentCameraModel) ) }
如果你的Fragment嵌套层级超过1层,就连续调用requireParentFragment()向上查找,直到拿到绑定目标导航图的宿主Fragment对应的控制器即可。
方案2:给嵌套容器配置独立NavHost(适合独立子导航流程场景)
如果这个FragmentContainerView本身就要承载一套独立的子导航流程,不要静态通过android:name写死加载CameraDetailsFragment,改成将其声明为独立的NavHostFragment,绑定专属子导航图:
首先替换原有布局代码:
<androidx.fragment.app.FragmentContainerView android:id="@+id/fragmentContainerView" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="false" app:navGraph="@navigation/nav_graph_camera" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
接着在绑定的nav_graph_camera导航图里,将CameraDetailsFragment设为起始目的地。如果需要从子导航流程跳转到外层导航图的目的地,要么在导航图里配置全局跳转action,要么通过共享ViewModel和宿主Fragment通信,由宿主Fragment触发外层导航。
- 凡是静态通过
android:name属性加载到FragmentContainerView的嵌套非NavHost Fragment,直接调用自身findNavController()都无法拿到外层NavHost的控制器,必须手动向上找父Fragment获取。 - 这类"找不到导航action/目的地"的嵌套Fragment导航报错,90%以上都是NavController实例拿错导致的,优先排查控制器来源。
内容的提问来源于stack exchange,提问作者Viacheslav Kolisnichenko

