如何在Navigation Component回退栈中查找Fragment实现无重建跳转并传参
问题描述
我在使用Navigation Component时,默认打开的是主Fragment。通过底部导航跳转到其他Fragment后,点击RecyclerView中的条目需要跳转回主Fragment并传递参数,但当前实现会导致主Fragment被重建,其关联的ViewModel也会跟着重建。我当前点击条目跳转的代码如下:
findNavController().navigate(NavGraphDirections.actionGlobalMainFragment(schemeId))
请问是否可以在回退栈中找到已存在的主Fragment,直接跳转至该实例而不触发重建,同时完成参数传递?
解决方案
可以实现,你的问题根源是直接调用全局action导航会往回退栈中新增一个主Fragment实例,原有实例依然保留在栈底,所以会触发重建。你可以通过弹回已存在的主Fragment回退栈条目+SavedStateHandle传递参数的方式实现需求,不会触发主Fragment和对应ViewModel的重建,实现步骤如下:
步骤1:修改跳转逻辑,复用已有主Fragment实例
在你点击RecyclerView条目的Fragment中,替换原来的navigate调用,改为先给主Fragment的回退栈条目存入参数,再弹回主Fragment:
val navController = findNavController() // 获取回退栈中已存在的主Fragment条目,R.id.mainFragment替换为你导航图中主Fragment对应的id val mainFragmentStackEntry = navController.getBackStackEntry(R.id.mainFragment) // 存入需要传递的参数,支持任意可序列化/Parcelable类型 mainFragmentStackEntry.savedStateHandle["schemeId"] = schemeId // 弹出主Fragment之上的所有回退栈条目,回到已有主Fragment实例,inclusive设为false表示不弹出主Fragment本身 navController.popBackStack(R.id.mainFragment, false)
步骤2:在主Fragment中接收参数
在主Fragment的onViewCreated方法中监听SavedStateHandle的参数变化即可:
// 监听参数传递 findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Int>("schemeId")?.observe(viewLifecycleOwner) { schemeId -> // 这里处理拿到的schemeId逻辑 // 处理完成后移除参数,避免返回主Fragment时重复触发回调 findNavController().currentBackStackEntry?.savedStateHandle?.remove<Int>("schemeId") }
注意事项
- 如果主Fragment因为系统内存不足被意外回收,SavedStateHandle会自动保留参数,重建后依然可以正常拿到数据,不会出现参数丢失的问题
- 如果你使用Safe Args,也可以将参数封装到Safe Args生成的类中再存入SavedStateHandle,用法和普通参数一致
- 该方案同时兼容有入场/退场动画的场景,和正常导航的体验保持一致
内容的提问来源于stack exchange,提问作者SoulReaver313
相关产品推荐
相关产品推荐

