You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:24:01