Android Navigation切换页面时Safe Args参数持续留存问题如何解决?
问题原因
使用Navigation组件搭配底部导航时,同一目的地的Fragment实例默认会被复用,仅会销毁重建视图(执行onDestroyView -> onCreateView生命周期),实例本身不会被销毁。
而Safe Args的参数是存储在Fragment的arguments Bundle对象中,只要Fragment实例存在,arguments内存储的数值就不会自动重置。你设置的默认null值仅在Fragment首次创建、arguments中无对应参数key时生效,一旦参数被赋值后,后续回到该Fragment都不会再读取默认值,因此会出现参数残留的问题。
解决方案
提供两种可直接落地的方案,可根据业务需求选择:
方案1:参数消费后手动清空(改动最小)
仅需在A Fragment消费完参数后,手动移除arguments内对应的参数key即可,下次回到Fragment时就会自动读取默认的null值。
修改后A Fragment的onViewCreated代码如下:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) args.workout?.let { workout -> vm.addRoutine(workout) // 新增这行,消费完直接删除参数,避免残留 arguments?.remove("workout") } vm.items.observe(viewLifecycleOwner) { updatedItems -> adapter.setItems(updatedItems) } }
方案2:使用官方推荐的Fragment返回结果API(无残留隐患,最佳实践)
不需要用Safe Args回传参数,改用Android官方提供的FragmentResultAPI,该API的回调是一次性的,仅在目标页面返回时触发一次,天然不存在参数残留问题:
- 先删除nav_graph中为A Fragment配置的
workout参数配置,不需要再用Safe Args接收回传值 - 在A Fragment的
onViewCreated中注册结果回调:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 注册返回结果监听,仅当B页面返回时触发 setFragmentResultListener("workout_request_key", viewLifecycleOwner) { _, bundle -> val workout = bundle.getString("workout") workout?.let { vm.addRoutine(it) } } vm.items.observe(viewLifecycleOwner) { updatedItems -> adapter.setItems(updatedItems) } }
- 在B Fragment需要返回A的位置,替换原有Safe Args传值逻辑:
// 先设置返回结果 setFragmentResult("workout_request_key", bundleOf("workout" to "你要回传的参数值")) // 再执行返回操作 findNavController().popBackStack()
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

