使用Jetpack Navigation返回Fragment后RecyclerView SelectionTracker选中丢失如何解决
问题根因
使用 Jetpack Navigation 跳转时,前一个 Fragment 仅销毁视图层,Fragment 实例会保留在回退栈中,并不会触发 onSaveInstanceState 回调。你当前把选中状态存到 savedInstanceState 的逻辑只有系统销毁 Fragment 实例时才会执行,正常跳转返回时 savedInstanceState 为空,自然无法恢复选中状态。
其次你当前的代码是先恢复状态、再加载列表数据,空列表状态下恢复选中状态也是无效的。
修复步骤
1. 新增实例变量存储选中状态
因为 Fragment 实例不会在导航跳转时销毁,直接用实例变量存储选中的 key 即可:
class SelectVideoForCourseFragment : Fragment(R.layout.fragment_select_video_for_course) { // 新增变量存储选中的key集合 private var savedSelection: Set<String>? = null // 原有代码不变... }
2. 监听选中变化实时存储
初始化 SelectionTracker 后添加选中监听,实时更新存储的选中状态:
private fun initializeRecyclerView(savedInstanceState: Bundle?) { // 原有初始化逻辑不变... selectionTracker = SelectionTracker.Builder(/*原有参数不变*/).build() adapter.tracker = selectionTracker // 新增选中监听 selectionTracker.addObserver(object : SelectionTracker.SelectionObserver<String>() { override fun onSelectionChanged() { super.onSelectionChanged() // 实时保存选中的key savedSelection = selectionTracker.selection.toSet() } }) // 原有savedInstanceState恢复逻辑保留,作为系统杀进程场景的兜底 if (savedInstanceState != null) { selectionTracker.onRestoreInstanceState(savedInstanceState) savedSelection = savedInstanceState.getStringArrayList("saved_selection")?.toSet() } }
3. 列表加载完成后再恢复选中状态
AsyncListDiffer 提交列表是异步操作,需要等列表更新完成后再恢复选中状态,先修改 Adapter 的提交方法添加完成回调:
class MediaListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() { // 修改submitItems方法添加完成回调 fun submitItems(updatedItems: List<Any>, onSubmitComplete: (() -> Unit)? = null) { differ.submitList(updatedItems) { onSubmitComplete?.invoke() } } // 原有代码不变... }
然后修改数据加载的 Observer,等列表提交完成后恢复选中:
private fun fetchMedias() { val mediaRepo = MediaRepo() mediaRepo.getVideos(contentResolver).observe(viewLifecycleOwner) { adapter.submitItems(it) { // 列表更新完成后恢复选中状态 savedSelection?.let { selectedKeys -> selectionTracker.setItemsSelected(selectedKeys, true) } } } }
4. 兜底兼容系统杀进程场景
保留原有 onSaveInstanceState 逻辑,同时额外存储我们的选中集合,防止后台进程被回收时状态丢失:
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) selectionTracker.onSaveInstanceState(outState) // 额外存储选中集合兜底 outState.putStringArrayList("saved_selection", ArrayList(savedSelection.orEmpty())) }
内容的提问来源于stack exchange,提问作者Alif Hasnain
相关产品推荐
相关产品推荐

