1.前言
2.工具類要點(diǎn)
2.1 聲明并初始化AsyncListDiffer
private val mDiffer: AsyncListDiffer<T>
2.2 創(chuàng)建DiffUtil.ItemCallback<T>,實(shí)現(xiàn)抽象方法
abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean
abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean
2.3 更新數(shù)據(jù)
fun setData(list: MutableList<T>?) {
val newList: MutableList<T> = ArrayList()
newList.addAll(list ?: ArrayList())
mDiffer.submitList(newList) // 更新數(shù)據(jù)(setData()+notify())
}
3. 注意事項(xiàng)
3.1 不能重復(fù)提交同一個(gè)列表
- 更新數(shù)據(jù)前(調(diào)用submitList(List<T> newList))盈蛮,請(qǐng)勿對(duì)"已被設(shè)置進(jìn)DiffUtil的list數(shù)據(jù)"進(jìn)行操作儡司。
- 需重新創(chuàng)建list暇唾,以便DiffUtil進(jìn)行兩個(gè)新舊列表間對(duì)比。如舉例。
3.2 錯(cuò)誤示范
mData.add(...)
mAdapter.submitList(mData)
3.3 引發(fā)此問題原因
public class AsyncListDiffer<T> {
// 更新數(shù)據(jù)
public void submitList(@Nullable final List<T> newList, @Nullable final Runnable commitCallback) {
// incrementing generation means any currently-running diffs are discarded when they finish
final int runGeneration = ++mMaxScheduledGeneration;
if (newList == mList) { // 此處進(jìn)行了過濾
// nothing to do (Note - still had to inc generation, since may have ongoing work)
if (commitCallback != null) {
commitCallback.run();
}
return;
}
...
}
}
4. 基類封裝實(shí)現(xiàn)
使用DiffUtil進(jìn)行RecyclerView數(shù)據(jù)的對(duì)比&刷新澎嚣,把相關(guān)api進(jìn)行二次封裝击吱,以便為了更簡(jiǎn)單調(diào)用淋淀。
4.1 BaseRecyclerDifferItemCallBack
- 對(duì)DiffUtil.ItemCallback<T>進(jìn)行二次封裝。
- RecyclerView的dapter作為參數(shù)覆醇,把對(duì)比函數(shù)回調(diào)到Adapter進(jìn)行實(shí)現(xiàn)朵纷。
class BaseRecyclerDifferItemCallBack<T>(adapter: BaseRecyclerDifferAdapter<T>?) :
DiffUtil.ItemCallback<T>() {
private var mAdapter: BaseRecyclerDifferAdapter<T>? = adapter
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
return mAdapter?.areItemsTheSame(oldItem, newItem)?: false
}
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return mAdapter?.areContentsTheSame(oldItem, newItem)?: false
}
}
4.2 BaseRecyclerDifferAdapter
- 對(duì)RecyclerView.Adapter進(jìn)行二次封裝,初始化AsyncListDiffer變量用于數(shù)據(jù)操作永脓。
- 創(chuàng)建數(shù)據(jù)對(duì)比抽象方法袍辞,用于此Adapter子類實(shí)現(xiàn)
abstract class BaseRecyclerDifferAdapter<T> : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val mDiffer: AsyncListDiffer<T> by lazy {
// 數(shù)據(jù)的操作由AsyncListDiffer實(shí)現(xiàn)
AsyncListDiffer(this, BaseRecyclerDifferItemCallBack<T>(this))
}
fun getCurrentData(): MutableList<T> {
return mDiffer.currentList
}
/**
* 設(shè)置數(shù)據(jù)
* @param list MutableList<T>?
*/
fun setData(list: MutableList<T>?){
val newList: MutableList<T> = ArrayList()
newList.addAll(list?: ArrayList())
mDiffer.submitList(newList)
}
/**
* 添加數(shù)據(jù)
* @param beans Array<out T>
*/
fun addData(vararg beans: T) {
val newList: MutableList<T> = ArrayList()
newList.addAll(mDiffer.currentList)
beans.forEach { bean ->
newList.add(bean)
}
mDiffer.submitList(newList)
}
/**
* 加載更多
* @param list MutableList<T>?
*/
fun loadMore(list: MutableList<T>?){
val newList: MutableList<T> = ArrayList()
newList.addAll(mDiffer.currentList)
newList.addAll(list?: ArrayList())
mDiffer.submitList(newList)
}
/**
* 刪除數(shù)據(jù)
* @param index Int
*/
fun removeData(index: Int) {
val newList: MutableList<T> = ArrayList()
val currentList = mDiffer.currentList
if (currentList.isNotEmpty() && index in 0 until currentList.size) {
newList.addAll(currentList)
newList.removeAt(index)
mDiffer.submitList(newList)
}
}
/**
* 清空數(shù)據(jù)
*/
fun clear() {
mDiffer.submitList(null)
}
abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean
abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean
4.2 業(yè)務(wù)Adapter實(shí)現(xiàn)
- 舉例說明BaseRecyclerDifferAdapter使用方式
- 以下為偽代碼,僅包含關(guān)鍵實(shí)現(xiàn)
class RVDifferAdapter(context: Context) : BaseRecyclerDifferAdapter<RVDifferBean>() {
private var mContext: Context = context
/**
* Item對(duì)比
*/
override fun areItemsTheSame(oldItem: RVDifferBean, newItem: RVDifferBean): Boolean {
return oldItem.id == newItem.id // 比較邏輯自行實(shí)現(xiàn)
}
/**
* Content對(duì)比
*/
override fun areContentsTheSame(oldItem: RVDifferBean, newItem: RVDifferBean): Boolean {
return oldItem.name == newItem.name // 比較邏輯自行實(shí)現(xiàn)
}
private var mInflater: LayoutInflater = LayoutInflater.from(context)
/**
* 獲取單條item數(shù)據(jù)
*
* @param position
* @return
*/
private fun getItemAtPosition(position: Int): RVDifferBean? {
val itemCount: Int = itemCount
return if (itemCount != 0 && position in 0 until itemCount) {
getCurrentData()[position]
} else {
null
}
}
override fun getItemCount(): Int {
return getCurrentData().size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
super.onBindViewHolder(holder, position, payloads)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
}
}
參考文檔:
官方文檔地址:[https://developer.android.google.cn/reference/kotlin/androidx/recyclerview/widget/DiffUtil]