DiffUtils 是Support-v7:24:2.0中,更新的工具类。app
DiffUtil是一个实用程序类,能够计算两个列表之间的差别,并输出将第一个列表转换为第二个列表的更新操做列表。ide
它主要是为了配合 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、notifyItemRangeChangedspa
Adaptercode
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);
复制代码
局部刷新子Viewget
若是使用 notifyItemChanged(int position, @Nullable Object payload) 方法,则会回调it
onBindViewHolder(@NonNull VH holder, int position,@NonNull List payloads) 方法。io
注意 若是有HeaderView Position没有算头部有问题class