前言
在使用RecycerView时,数据集合发生变化后,刷新视图最简单粗暴的方式就是调用 adapter.notifyDataSetChanged() 进行全局刷新,稍微优雅一点的方式会使用 adapter.notifyItemInserted() 或者 adapter.notifyItemRemoved()实现元素的插入以及删除的视图刷新。与全局刷新相比,这种方式不仅有过渡动画而且效率更高。但是随着数据集合中的元素变多,元素的插入删除操作变多,手动实现变得不太理智,因此,DiffUtil的作用就显现出来了。
DiffUtil简介
文档介绍: DiffUtil is a utility class that calculates the difference between two lists and outputs a list of update operations that converts the first list into the second one. 翻译过来就是计算数据集变化前后的差异,然后将这些变化应用于一个数据集中,所以我们只需要给出两个数据集,它就能帮我们实现元素的插入删除的操作,听起来很简单的样子,其实实现也并不复杂。
DiffUtil使用
老规矩,先定义一个数据类。
data class Msg(
var id: Int,
var name: String,
var msg: String,
var time: String,
var type: Int) {
}
定义一个Adapter,这里使用了DataBinding,代码比较简洁。
class ChatAdapter(
val ctx: Context,
var msgs: MutableList<Msg>) : RecyclerView.Adapter<ChatAdapter.ViewHolder>() {
inner class ViewHolder(private var binding: LayoutMsgItemBinding) : RecyclerView.ViewHolder(binding.root){
fun getBinding() : LayoutMsgItemBinding{
return binding
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(DataBindingUtil
.inflate(LayoutInflater.from(ctx),R.layout.layout_msg_item,parent,false))
}
override fun getItemCount(): Int {
return msgs.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.getBinding().setVariable(BR.msg,msgs[position])
holder.getBinding().executePendingBindings()
}
}
重点来了,看看DiffUtil的使用方式。在DiffUtil类中,只有两个公有静态方法,那么基本上就是用它来实现了。
/**
* Calculates the list of update operations that can covert one list into the other one.
*
* @param cb The callback that acts as a gateway to the backing list data
*
* @return A DiffResult that contains the information about the edit sequence to convert the
* old list into the new list.
*/
@NonNull
public static DiffR