是什么
DiffUtil是一个工具类,当你的RecyclerView需要更新数据时,将新旧数据集传给它,它就能快速告知adapter有哪些数据需要更新。就相当于如果改变了就对某个item刷新,没改变就没刷新,可以简称为局部刷新。
使用
/**
* 当使用Diffutils的时候,这是一个计算2个list不同的回调函数
*/
public abstract static class Callback {
/**
* 得到老的数据源大小
*/
public abstract int getOldListSize();
/**
* 得到新的数据源大小
*/
public abstract int getNewListSize();
/**
*
* 被DiffUtil调用,用来判断 两个对象是否是相同的Item。
* 例如,如果你的Item有唯一的id字段,这个方法就判断id是否相等。
*/
public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);
/**
* 用来检查 两个item是否含有相同的数据
* 这个方法仅仅在areItemsTheSame()返回true时,才调用。
*/
public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);
/**
* 当areItemsTheSame(int, int)返回true,且areContentsTheSame(int, int)返回false时,DiffUtils会回调此方法,
* 去得到这个Item(有哪些)改变的payload。
* 例如,如果你用RecyclerView配合DiffUtils,你可以返回 这个Item改变的那些字段,可以用那些信息去执行正确的动画
* 返回 一个 代表着新老item的改变内容的 payload对象,
*/
@Nullable
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return null;
}
}
Callback用来设置数据源的比较规则,判断新老数据之间的差异。
基础使用
Callback
package com.example.helloview.recyclerview.diffutils
import androidx.recyclerview.widget.DiffUtil
class UserCallBack(val oldList: List<UserBean>, val newList: List<UserBean>) :
DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition].id == newList[newItemPosition].id
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldBean = oldList[oldItemPosition]
val newBean = newList[newItemPosition]
return oldBean.firstName == newBean.firstName && oldBean.lastName == newBean.lastName
}
}
局部刷新
private fun diffData() {
val newList = mutableListOf<UserBean>()
val oldList = mutableListOf<UserBean>()
newList.addAll(data)
oldList.addAll(data)
newList[2] = UserBean(20,"diff--","数据更新")
val callback = UserCallBack(oldList,newList)
//计算差异item
val diffResult = DiffUtil.calculateDiff(callback,true)
// 注意此处一定要将新数据设置给Adapter
// 否则会造成ui刷新了但数据未更新的bug
mAdapter?.setData(newList)
//调用adapter的局部更新方法
diffResult.dispatchUpdatesTo(mAdapter!!)
}
- 首先DiffUtil.calculateDiff()这个方法是执行在主线程的,如果新旧数据List比较大,那么这个方法铁定是会阻塞主线程的
- 计算出DiffResult后,咱们必须要将新数据设置给Adapter,然后才能调用DiffResult.dispatchUpdatesTo(Adapter)刷新ui,然而很多人都会忘记这一步。
网友评论