使用Jetpack Navigation在Fragment间传参时原有列表被清空如何解决
问题根因
你当前使用findNavController().navigate(action)从Fragment2返回Fragment1的写法,本质是在返回栈中新增了一个全新的Fragment1实例,原有存着列表数据的Fragment1实例仍然留在返回栈中,新实例没有历史列表数据才会出现清空现象。
你提到的屏幕旋转、切后台数据正常,也验证了这一点:这两个场景下都是原有Fragment1实例重建,绑定的ViewModel没有销毁,所以数据正常保留;而你主动跳转创建的是新Fragment1实例,对应新的ViewModel实例,自然没有历史列表数据。
解决方法(官方推荐方案)
使用Navigation组件自带的回退栈数据传递能力,不要主动创建新的Fragment1实例,直接返回原有实例并传递新增的客户数据即可,步骤如下:
- 在Fragment1的
onViewCreated方法中注册返回数据监听器
val navController = findNavController() // 监听key为new_client的返回数据,类型为你定义的Clients类 navController.currentBackStackEntry?.savedStateHandle?.getLiveData<Clients>("new_client") ?.observe(viewLifecycleOwner) { newClient -> // 拿到新增的客户数据,更新现有列表即可 yourClientList.add(newClient) yourRecyclerAdapter.notifyItemInserted(yourClientList.size - 1) // 消费完数据后移除,避免重复触发 navController.currentBackStackEntry?.savedStateHandle?.remove<Clients>("new_client") }
- 修改Fragment2的提交逻辑,删除原有跳转代码,改用回退传递数据的方式:
val client = Clients(id,name,secondName,thirdName, address, creditCard, bankNum) // 将数据存入前一个页面(即Fragment1)的回退栈状态实例中 findNavController().previousBackStackEntry?.savedStateHandle?.set("new_client", client) // 直接回退到上一个页面,不会创建新的Fragment1实例 findNavController().popBackStack()
注意事项
- 不要使用
navigate()执行回退操作,popBackStack()才是官方指定的返回上一页面的API,两者行为逻辑完全不同 - 该方案不需要修改你的导航图配置,也不需要调整现有ViewModel的作用域,适配你当前的技术栈
内容的提问来源于stack exchange,提问作者Андрей Ерошенко
相关产品推荐
相关产品推荐

