是什么
DiffUtil是一個工具類告材,當你的RecyclerView需要更新數(shù)據(jù)時枷踏,將新舊數(shù)據(jù)集傳給它凿可,它就能快速告知adapter有哪些數(shù)據(jù)需要更新繁仁。就相當于如果改變了就對某個item刷新涉馅,沒改變就沒刷新,可以簡稱為局部刷新黄虱。
使用
/**
* 當使用Diffutils的時候稚矿,這是一個計算2個list不同的回調(diào)函數(shù)
*/
public abstract static class Callback {
/**
* 得到老的數(shù)據(jù)源大小
*/
public abstract int getOldListSize();
/**
* 得到新的數(shù)據(jù)源大小
*/
public abstract int getNewListSize();
/**
*
* 被DiffUtil調(diào)用,用來判斷 兩個對象是否是相同的Item捻浦。
* 例如晤揣,如果你的Item有唯一的id字段,這個方法就判斷id是否相等默勾。
*/
public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);
/**
* 用來檢查 兩個item是否含有相同的數(shù)據(jù)
* 這個方法僅僅在areItemsTheSame()返回true時碉渡,才調(diào)用。
*/
public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);
/**
* 當areItemsTheSame(int, int)返回true母剥,且areContentsTheSame(int, int)返回false時滞诺,DiffUtils會回調(diào)此方法,
* 去得到這個Item(有哪些)改變的payload环疼。
* 例如习霹,如果你用RecyclerView配合DiffUtils,你可以返回 這個Item改變的那些字段炫隶,可以用那些信息去執(zhí)行正確的動畫
* 返回 一個 代表著新老item的改變內(nèi)容的 payload對象淋叶,
*/
@Nullable
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return null;
}
}
Callback用來設置數(shù)據(jù)源的比較規(guī)則,判斷新老數(shù)據(jù)之間的差異伪阶。
基礎使用
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--","數(shù)據(jù)更新")
val callback = UserCallBack(oldList,newList)
//計算差異item
val diffResult = DiffUtil.calculateDiff(callback,true)
// 注意此處一定要將新數(shù)據(jù)設置給Adapter
// 否則會造成ui刷新了但數(shù)據(jù)未更新的bug
mAdapter?.setData(newList)
//調(diào)用adapter的局部更新方法
diffResult.dispatchUpdatesTo(mAdapter!!)
}
- 首先DiffUtil.calculateDiff()這個方法是執(zhí)行在主線程的煞檩,如果新舊數(shù)據(jù)List比較大,那么這個方法鐵定是會阻塞主線程的
- 計算出DiffResult后栅贴,咱們必須要將新數(shù)據(jù)設置給Adapter斟湃,然后才能調(diào)用DiffResult.dispatchUpdatesTo(Adapter)刷新ui,然而很多人都會忘記這一步檐薯。