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

使用DiffUtil更新列表少量指定项是否必须新建对比列表

核心结论

不需要强制创建全量拷贝的全新列表实例,但有一条不能碰的红线:绝对不能直接修改Adapter当前已持有的列表的内部元素,且提交给DiffUtil比对的新旧两个列表都必须是不可变状态(提交后不能再修改元素内容、调整顺序),这是DiffUtil能正常计算差异、不出现UI刷新错乱的核心前提。

现有实现的问题

你贴的实现里每次更新都通过map遍历全量列表做转换,哪怕100个项里只需要改2、3个动态项,也要把剩下90多个不需要改动的非动态项全部遍历一遍,生成新的列表引用。当列表长度更大、动态项更新频率高的时候,这部分无意义的遍历和对象创建会带来不必要的性能开销。

DiffUtil本身的比对逻辑并不要求你把所有元素都重新生成一遍,它只会对比新旧列表对应位置的元素:如果元素的唯一标识(itemId/你在areItemsTheSame里的判断逻辑)一致,且内容比对(areContentsTheSame)一致,就会直接跳过这个项的刷新处理。

更优的低开销更新方案

你可以根据自己的业务场景选下面几种方案,都不需要做全量列表拷贝:

  • 精准局部刷新(性能最高,零Diff计算开销)
    如果你能明确拿到每个要更新的动态项在列表中的位置,完全不需要走submitList触发全量Diff计算,直接遍历待更新的项,找到对应position后调用adapter.notifyItemChanged(position, payload)即可。
    配合payload参数可以实现定向绑定,只会刷新对应项里变化的控件,连其他非动态项的onBindViewHolder都不会触发,性能是所有方案里最好的。
  • 最小修改构建新列表(适配必须走submitList的场景)
    如果你需要统一走ListAdapter的submitList流程,不需要全量map转换,只需要基于原列表做最小范围的修改即可:
    fun replaceDynamicItems(dynamicItems: List<DynamicItem>) {
        // 仅基于当前列表生成一个可变副本,不需要遍历转换所有元素
        val listToSubmit = currentList.toMutableList()
        dynamicItems.forEach { updatedItem ->
            // 找到当前动态项对应的位置,匹配逻辑可以替换成你自己的业务规则(比如按ID匹配)
            val targetIndex = listToSubmit.indexOfFirst { 
                it is DynamicItem && it.uniqueId == updatedItem.uniqueId 
            }
            if (targetIndex != -1) {
                // 只替换需要更新的项,其余元素全部复用原引用
                listToSubmit[targetIndex] = updatedItem
            }
        }
        adapter.submitList(listToSubmit)
    }
    
    这种写法下,不需要改动的非动态项会直接保留原引用,DiffUtil比对时发现这些项的引用、内容都没有变化,会直接跳过比对,开销比全量map低很多。
  • 开启稳定ID进一步加速Diff计算
    给Adapter开启setHasStableIds(true),并重写getItemId()返回每个列表项的唯一固定标识,DiffUtil在比对时会优先通过ID判断是否为同一个项,差异计算的速度会进一步提升。
避坑提醒

禁止直接修改Adapter当前持有的列表:比如拿到currentList之后直接修改对应位置的元素,既不提交新列表也不调用notify方法,这种操作会导致DiffUtil做差异比对时,拿到的旧列表已经被篡改,计算出来的差异结果完全错误,最终出现列表项错位、内容错乱的问题。也不要在修改元素后直接调用notifyDataSetChanged(),这种方式会触发全列表重绘,性能最差。

内容的提问来源于stack exchange,提问作者sssrigo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:57:19