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

如何获取RecyclerView更新完成回调 避免列表新旧数据混杂展示

解决RecyclerView更新与数据源修改冲突的方案

核心前置规则

  • 永远不要直接修改Adapter绑定的ArrayList<User>实例,后台任务拿到新数据后先生成独立的数据集副本,再触发Adapter更新,从根源避免读写冲突。

方案1:使用AdapterDataObserver监听更新完成

这是官方提供的标准监听Adapter视图更新完成的方式,适配所有RecyclerView版本:

// 注册观察者
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
    override fun onChanged() {
        super.onChanged()
        // 全局更新(notifyDataSetChanged)完成回调,此时可以执行下一次列表更新操作
        executePendingUserListUpdate()
    }

    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        super.onItemRangeInserted(positionStart, itemCount)
        // 条目插入更新完成回调
        executePendingUserListUpdate()
    }

    override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
        super.onItemRangeChanged(positionStart, itemCount)
        // 条目修改更新完成回调
        executePendingUserListUpdate()
    }

    // 按需重写onItemRangeRemoved、onItemRangeMoved等其他回调即可
})

注意:不需要监听的时候要调用unregisterAdapterDataObserver解绑,避免内存泄漏。

方案2:利用DiffUtil的完成回调(更推荐)

如果你用DiffUtil做增量更新,可以直接在提交更新的回调里拿到完成时机,性能比全局更新高很多:

// 后台线程计算Diff结果后,提交到Adapter
val diffResult = DiffUtil.calculateDiff(UserDiffCallback(oldList, newCopyList))
diffResult.dispatchUpdatesTo(adapter) {
    // 此处回调即为增量更新完成时机
    executePendingUserListUpdate()
}
// 同时把Adapter绑定的数据源替换为新的副本
adapter.userList = newCopyList

方案3:使用RecyclerView.post兜底

如果只是临时快速实现,可以给RecyclerView post任务,任务会在RecyclerView当前帧绘制完成后执行,此时视图更新已经结束:

adapter.notifyDataSetChanged();
recyclerView.post(() -> {
    // 视图更新完成,执行后续操作
    executePendingUserListUpdate();
});

内容的提问来源于stack exchange,提问作者M.Toy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:09:03