recyclerview优化 DiffUtils 局部刷新

DiffUtils 是Support-v7:24:2.0中,更新的工具类。

DiffUtil是一个实用程序类,可以计算两个列表之间的差异,并输出将第一个列表转换为第二个列表的更新操作列表。

它主要是为了配合 RecyclerView 使用,通过比对新、旧两个数据集的差异,生成旧数据到新数据的最小变动,然后对有变动的数据项,进行局部刷新。

class ComicDiffCallBack(private val mOldDataList: ArrayList<ComicBean>?, private val mNewDataList: ArrayList<ComicBean>?) : DiffUtil.Callback() {

    //两个对象是否是相同的Item,例如,如果你的Item有唯一的id字段,这个方法就 判断id是否相等。
    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        if (mOldDataList != null && mNewDataList != null) {
            val oldData = mOldDataList[oldItemPosition]
            val newData = mNewDataList[newItemPosition]
            if (oldData.id == newData.id) {
                return true
            }
            if (TextUtils.equals(oldData.title, newData.title)) {
                return true
            }
        }
        return false
    }

    override fun getOldListSize(): Int = mOldDataList?.size ?: 0

    override fun getNewListSize(): Int = mNewDataList?.size ?: 0

    //用来检查 两个item是否含有相同的数据
    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        if (mOldDataList != null && mNewDataList != null) {
            val oldData = mOldDataList[oldItemPosition]
            val newData = mNewDataList[newItemPosition]
            when {
                oldData.type != newData.type -> return false
                !TextUtils.equals(oldData.title, newData.title) -> return false
                !TextUtils.equals(oldData.cover, newData.cover) -> return false
                !TextUtils.equals(oldData.describe, newData.describe) -> return false
            }
        }
        return true
    }

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        if (mOldDataList == null || mNewDataList == null) {
            return null
        }
        val oldData = mOldDataList[oldItemPosition]
        val newData = mNewDataList[newItemPosition]
        val payload = Bundle()
        if (!TextUtils.equals(oldData.title, newData.title)) {
            payload.putString(KeyConst.MainComic.TITLE, newData.title)
        }
        if (!TextUtils.equals(oldData.cover, newData.cover)) {
            payload.putString(KeyConst.MainComic.COVER, newData.cover)
        }
        if (!TextUtils.equals(oldData.describe, newData.describe)) {
            payload.putString(KeyConst.MainComic.DESC, newData.describe)
        }
        if (payload.size() == 0) {
            return null
        }
        return payload
   }
}


data class ComicBean(var title:String,var cover: String,var describe:String)

object KeyConst {
    object MainComic {
       const val TITLE = "KEY_COMIC_TITLE"
       const val COVER = "KEY_COMIC_COVER"
       const val DESC = "KEY_COMIC_DESC"
   }
}
复制代码

DiffUtil可以得到一个变更集合DiffResult,DiffResult会根据数据的增删改去调用Adapter的notifyItemRangeInserted、notifyItemRangeRemoved、notifyItemMoved、notifyItemRangeChanged

Adapter

override fun onBindViewHolder(holder: ViewHolder?, position: Int, payloads: List<Any>?) {
    ComicBean t = mList[position]
    if (payloads != null) {
        val payload = payloads[0] as Bundle
        for (key in payload.keySet()) {
            when (key) {
                KeyConst.MainComic.TITLE -> holder?.setText(R.id.iv_img_small_title, t?.title)
                KeyConst.MainComic.COVER -> holder?.setImageLoad(R.id.iv_img_small_cover, t?.cover)
                KeyConst.MainComic.DESC -> {
                    holder?.setImageLoad(R.id.iv_img_small_cover, t?.cover)
                    holder?.getView<TextView>(R.id.iv_img_small_desc)?.apply {
                        visibility = View.VISIBLE
                        text = t?.describe
                    }
                }
            }
        }
    } else {
        holder?.setText(R.id.iv_img_small_title, t?.title)
        holder?.setImageLoad(R.id.iv_img_small_cover, t?.cover)
        holder?.getView<TextView>(R.id.iv_img_small_desc)?.apply {
            visibility = View.VISIBLE
            text = t?.describe
        }
    }
}
复制代码

使用

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new ItemDiffCallBack(mList, mNewList));
diffResult.dispatchUpdatesTo(mAdapter);
复制代码

局部刷新子View

如果使用 notifyItemChanged(int position, @Nullable Object payload) 方法,则会回调

onBindViewHolder(@NonNull VH holder, int position,@NonNull List payloads) 方法。

注意 如果有HeaderView Position没有算头部有问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值