DiffUtil 用于计算两个列表之间的差异并输出将第一个列表转换为第二个列表的更新操作列表,它可用于计算 RecyclerView 适配器的更新.
官方简介语法
出现原先:
DiffUtil 同步方案处理大量数据的时候耗时较长衍生出异步方案
解决方案:
AsyncListDiffer 在后台通过 DiffUtil 计算两个列表之间的差异的助手
主要方案:
同步方案:主要方法 DiffUtil.calculateDiff() ,DiffUtil.Callback(),DiffResult.dispatchUpdatesTo()
Adapter代码(主要参考onBindViewHolder)
class MainAdapter(mContext: Context) : KtAdapter(mContext) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
var binding = DataBindingUtil.inflate(
LayoutInflater.from(mContext),
R.layout.item_main_one,
parent,
false
)
var holder = KtDataBindingViewHolder(binding.root)
holder.binding = binding
return holder
}
/**
* @param payloads A non-null list of merged payloads. Can be empty list if requires full
* update.
*/
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList
) {
// payloads 为null 整条数据刷新
if (payloads.isEmpty() || payloads.size <= 0) {
super.onBindViewHolder(holder, position, payloads)
} else {
//局部更新 不会更新整个item 更新指定的控件
var bundle = payloads.get(0) as Bundle
if (bundle != null) {
var name = bundle.getString("name")
var phoneNum = bundle.getString("phoneNum")
var holder = holder as KtDataBindingViewHolder
var binding = holder.binding as ItemMainOneBinding
if (!TextUtils.isEmpty(name)) {
binding.tvName.text = name
}
if (!TextUtils.isEmpty(phoneNum)) {
binding.tvPhone.text = phoneNum
}
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
Log.e("绘制:", "" + position)
var holder = holder as KtDataBindingViewHolder
var binding = holder.binding as ItemMainOneBinding
binding.tvName.setText(getItem(position)!!.name)
binding.tvPhone.setText(getItem(position)!!.phoneNum)
}
}
方法介绍:
1:DiffUtil:主要方法工具类
2:DiffUtil.calculateDiff(callback,list),计算可以将一个列表转换为另一个列表的更新操作列表。
3:Callback :计算两个不通集合的回调 (自己实现这个类处理,两个数据合并成一个数据)
A:getNewListSize() 新数据集合个数
B:getOldListSize() 旧数据的个数
C:areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): 根据某个属性判断是否是一个数据(某唯一值判断,一般是ID)
D:areContentsTheSame(oldItemPosition: Int, newItemPosition: Int):同一个数据参数属性是否相同(对象的属性)
E:getChangePayload(oldItemPosition: Int, newItemPosition: Int) :属性变动执行此方法(单条数据局部刷新需要执行)
代码:
import android.os.Bundle
import android.text.TextUtils
import androidx.recyclerview.widget.DiffUtil
/**
* @author wkq
*
* @date 2021年09月06日 14:33
*
*@des
*
*/
class RecyclerViewDiffCallBack(oldList: List, newList: List) : DiffUtil.Callback() {
var oldList: List? = null
var newList: List? = null
init {
this.oldList = oldList
this.newList = newList
}
//旧数据集的长度;
override fun getOldListSize(): Int {
if (oldList.isNullOrEmpty()) {
return 0
} else {
return oldList!!.size
}
}
//获取新数据长度
override fun getNewListSize(): Int {
if (newList.isNullOrEmpty()) {
return 0
} else {
return newList!!.size
}
}
//判断是否是同一个item 为true 进入areContentsTheSame
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
if (oldList == null || oldList == null) return false
var oldItemId = oldList!![oldItemPosition].id
var newItemId = newList!![newItemPosition].id
return oldItemId!!.equals(newItemId)
}
// 如果item相同,此方法用于判断是否同一个 Item 的内容也相同 为false进入 getChangePayload
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
if (oldList == null || oldList == null) return false
var oldItem = oldList!![oldItemPosition].toString()
var newItem = newList!![newItemPosition].toString()
return oldItem.equals(newItem)
}
// 局部刷新 返回null 整条数据刷新
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
var oldItem = oldList!![oldItemPosition]
var newItem = newList!![newItemPosition]
var bundle=Bundle()
// onBindViewHolder 实现三个参数 payloads 第一个数据为 封装的bundle
if (!TextUtils.equals(oldItem.name,newItem.name)){
bundle.putString("name",newItem.name)
}
if (!TextUtils.equals(oldItem.icon,newItem.icon)){
bundle.putString("icon",newItem.name)
}
if (!TextUtils.equals(oldItem.phoneNum,newItem.phoneNum)){
bundle.putString("phoneNum",newItem.phoneNum)
}
return bundle
}
}
4: DiffResult :DiffUtil.calculateDiff()获取差分数据的结果
5:DiffResult.dispatchUpdatesTo(adapter):将更新事件分派给给定的适配器。
代码:
private fun setNewData() {
var userList = ArrayList()
for (index in 0..mAdapter!!.getItems()!!.size) {
var userInfo = UserInfo()
if (index == 0) {
userInfo.name = "开始"
} else if (index == mAdapter!!.getItems()!!.size) {
userInfo.name = "结束"
} else {
userInfo.name = "测试" + index
}
userInfo.id = index
userInfo.phoneNum = "1853853738" + index
userList.add(userInfo)
}
var result = DiffUtil.calculateDiff(RecyclerViewDiffCallBack(mAdapter!!.getItems()!!, userList))
mAdapter!!.setDatas(userList)
result.dispatchUpdatesTo(mAdapter!!)
}