IndexOutOfBoundsException ListAdapter

问题描述

我正在从通常的 RecyclerView 迁移到 listadapter

abstract class BaseAdapter<T>(
@LayoutRes
val normalLayoutId: Int,@LayoutRes
val loadingLayoutId: Int = R.layout.progress_loading,sm: (T,T) -> Boolean,val itemsCells: ArrayList<T?> = ArrayList()
  ) : listadapter<T,RecyclerView.ViewHolder>(TaskDiffCallbac(sm)) {
val VIEW_TYPE_ITEM = 0
val VIEW_TYPE_LOADING = 1

class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

class LoadingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

fun addData(dataViews: ArrayList<T>) {
    itemsCells.addAll(dataViews)
    this.submitList(dataViews)
    notifyDataSetChanged()
}


override fun getItemViewType(position: Int): Int {
    return if (getItem(position) == null) {
        VIEW_TYPE_LOADING
    } else {
        VIEW_TYPE_ITEM
    }
}

override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): RecyclerView.ViewHolder {
    return if (viewType == Constant.VIEW_TYPE_ITEM) {
        val view =
            LayoutInflater.from(parent.context).inflate(normalLayoutId,parent,false)
        ItemViewHolder(view)
    } else {
        val view =
            LayoutInflater.from(parent.context).inflate(loadingLayoutId,false)
        LoadingViewHolder(view)
    }
}

fun addLoadingView() {
    itemsCells.add(null)
    submitList(itemsCells)
}

fun removeLoadingView() {
    if (itemsCells.size != 0) {
        itemsCells.removeAt(itemsCells.size - 1)
       submitList(itemsCells)
    }
}

fun clearItems() {
    itemsCells.clear()
    submitList(itemsCells)
}

class TaskDiffCallbac<T>(val sm: (T,T) -> Boolean) : DiffUtil.ItemCallback<T>() {
    override fun areItemsTheSame(oldItem: T,newItem: T): Boolean {
        return sm(oldItem,newItem)
    }

    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: T,newItem: T): Boolean {
        return oldItem == newItem
    }
 }

}

但是在调试时我得到这个异常:

 java.lang.indexoutofboundsexception: Index: 20,Size: 20
2021-02-19 11:38:11.770 5602-5668/? E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
Process: com.timelysoft.shelter,PID: 5602
java.lang.indexoutofboundsexception: Index: 20,Size: 20
    at java.util.ArrayList.get(ArrayList.java:437)
    at androidx.recyclerview.widget.AsyncListDiffer$1$1.areItemsTheSame(AsyncListDiffer.java:306)
    at androidx.recyclerview.widget.DiffUtil.diffPartial(DiffUtil.java:268)
    at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:145)
    at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:105)
    at androidx.recyclerview.widget.AsyncListDiffer$1.run(AsyncListDiffer.java:292)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)

有什么问题?

解决方法

abstract class BaseAdapter<T>(
 @LayoutRes
 val normalLayoutId: Int,@LayoutRes
 val loadingLayoutId: Int = R.layout.progress_loading,sm: (T,T) -> Boolean,val itemsCells: ArrayList<T?> = ArrayList()
) : ListAdapter<T,RecyclerView.ViewHolder>(CustomDiffCallbac(sm)) {
val VIEW_TYPE_ITEM = 0
val VIEW_TYPE_LOADING = 1

class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

class LoadingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

fun addData(dataViews: ArrayList<T>) {
    itemsCells.addAll(dataViews)
    this.submitList(itemsCells)
}


override fun getItemViewType(position: Int): Int {
    return if (itemsCells[position] == null) {
        VIEW_TYPE_LOADING
    } else {
        VIEW_TYPE_ITEM
    }
}

override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): RecyclerView.ViewHolder {
    return if (viewType == Constant.VIEW_TYPE_ITEM) {
        val view =
            LayoutInflater.from(parent.context).inflate(normalLayoutId,parent,false)
        ItemViewHolder(view)
    } else {
        val view =
            LayoutInflater.from(parent.context).inflate(loadingLayoutId,false)
        LoadingViewHolder(view)
    }
}

fun addLoadingView() {
    itemsCells.add(null)
    submitList(itemsCells)
    notifyItemInserted(itemsCells.size-1)
}

fun removeLoadingView() {
    if (itemsCells.size != 0) {
        val index = itemsCells.size - 1
        itemsCells.removeAt(index)
       submitList(itemsCells)
        notifyItemRemoved(index)
    }
}

fun clearItems() {
    itemsCells.clear()
    submitList(itemsCells)
}

class CustomDiffCallbac<T>(val sm: (T,T) -> Boolean) : DiffUtil.ItemCallback<T>() {
    override fun areItemsTheSame(oldItem: T,newItem: T): Boolean {
        return sm(oldItem,newItem)
    }


    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: T,newItem: T): Boolean {
        return oldItem == newItem
    }
}

}