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