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

Android DiffUtil更新RecyclerView如何仅增删条目不移动已有内容

解决方案

你当前的实现问题出在areItemsTheSame全局返回true的逻辑,DiffUtil会误判所有位置的条目为同一对象,导致计算出不符合预期的移动操作,无法满足「仅新增/移除条目、不移动已展示条目」的需求。

修正后的实现代码

fun notifyChanges(newListSize: Int) {
    val oldSize = tilesNumber // 直接取当前Adapter已有的条目数,避免外部变量状态不一致
    val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            // 只有位置相同的条目判定为同一个,保证已有条目不会被移动
            return oldItemPosition == newItemPosition
        }

        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            // 已有条目内容无需更新,直接返回true即可
            return true
        }

        override fun getOldListSize() = oldSize
        override fun getNewListSize() = newListSize
    })

    tilesNumber = newListSize
    diff.dispatchUpdatesTo(this)
}

实现逻辑说明

  • 当newListSize > 旧条目数时:DiffUtil会判定从oldSize到newListSize - 1的区间为新增条目,自动触发notifyItemRangeInserted回调,前面已展示的条目不会有任何变动
  • 当newListSize < 旧条目数时:DiffUtil会判定从newListSize到oldSize - 1的区间为待移除条目,自动触发notifyItemRangeRemoved回调,保留的前newListSize个条目位置完全不变
  • 如果后续你需要支持条目内容更新,只需修改areContentsTheSame的逻辑,加入对应位置的内容对比即可,不影响条目不移动的特性

原有调用逻辑无需修改,仍可正常使用:

mAdapter.notifyChanges(columnNumber * rowNumber)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 19:15:03