java.lang.IndexOutOfBoundsException: Index: 3, Size: 13
·
java.lang.IndexOutOfBoundsException: Index: 3, Size: 13 at java.util.ArrayList.get(ArrayList.java:437) at androidx.recyclerview.widget.AsyncListDiffer$1$1.areItemsTheSame(AsyncListDiffer.java:305) at androidx.recyclerview.widget.DiffUtil.diffPartial(DiffUtil.java:233) 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) at java.lang.Thread.run(Thread.java:919)
index 3 size 13 应该是没的问题啊,为什么会报这个错误呢?
AsyncListDiffer.submitList() 会将新列表传递给后台线程的 DiffUtil 进行差异计算,整个过程需要 旧列表和新列表保持绝对稳定(不可修改)。如果在计算期间(后台线程执行时):
- 新列表被主线程或其他线程修改(如元素被删除、清空);
- 旧列表(上一次提交的列表)被意外修改;
就会导致 DiffUtil 在访问索引时,列表的实际大小已小于预期,从而触发越界异常(例如:原本大小为 13 的列表,计算期间被清空为 0,此时访问索引 0 就会报错)。
简单来说就是多次执行原始数据和新数据不一样导致,也可以说是异步问题
解决方法:
1. 确保每次提交新的列表实例
每次提交时创建新的列表对象(避免复用旧列表引用),让 DiffUtil 能正确识别数据变化
// 错误:复用同一列表实例(修改后再次提交)
val list = mutableListOf("A", "B")
adapter.submitList(list)
list.add("C")
adapter.submitList(list) // 危险:引用未变,DiffUtil 可能误判
// 正确:每次提交新列表(使用 toList() 或 copy() 创建新实例)
val list = mutableListOf("A", "B")
adapter.submitList(list.toList()) // 转为不可变列表(新实例)
list.add("C")
adapter.submitList(list.toList()) // 新实例,安全
2. 限制提交频率(防抖动)
使用 防抖动(Debounce) 避免短时间内多次提交,例如通过 Coroutine 延迟提交,只执行最后一次调用:
private var submitJob: Job? = null
fun submitData(newList: List<String>) {
// 取消上一次未执行的提交
submitJob?.cancel()
// 延迟 100ms 提交,若 100ms 内再次调用则覆盖
submitJob = GlobalScope.launch(Dispatchers.Main) {
delay(100)
adapter.submitList(newList.toList())
}
}
更多推荐



所有评论(0)