BaseRecyclerViewAdapterHelper icon indicating copy to clipboard operation
BaseRecyclerViewAdapterHelper copied to clipboard

setDiffNewData异步diff数据时,可能导致IndexOutOfBoundsException

Open zhujunhua2012 opened this issue 4 years ago • 7 comments

局部刷新时, 使用#setDiffNewData异步diff数据,此时在RecyclerView中下拉刷新(在BrvahAsyncDiffer进行异步diff的同时),会加载更早的数据,直接使用 getData().addAll(0, earlierDataList),可能导致IndexOutOfBoundsException。

2022-01-07 13:44:14.986, E/WTag-CrashHandler, java.lang.IndexOutOfBoundsException: Index: 4, Size: 40
	at java.util.ArrayList.get(ArrayList.java:437)
	at com.chad.library.adapter.base.diff.BrvahAsyncDiffer$submitList$1$result$1.areItemsTheSame(BrvahAsyncDiffer.kt:138)
	at androidx.recyclerview.widget.DiffUtil.forward(DiffUtil.java:239)
	at androidx.recyclerview.widget.DiffUtil.midPoint(DiffUtil.java:198)
	at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:146)
	at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:106)
	at com.chad.library.adapter.base.diff.BrvahAsyncDiffer$submitList$1.run(BrvahAsyncDiffer.kt:128)
	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:929)

getData().addAll(0, earlierDataList)这个操作对数据源进行了更改,使得BrvahAsyncDiffer#submitList中的val oldList: List<T> = adapter.data 这个oldList数据发生了变化。 但是目前的场景,就是需要在已有数据之前添加earlierDataList,有其他方法吗?(不想整个替换数据源)

zhujunhua2012 avatar Jan 07 '22 09:01 zhujunhua2012

#setDiffNewData这个使用异步diff BrvahAsyncDiffer#submitList,应该是参考的官方的AsyncListDiffer#submitList。 但是官方的AsyncListDiffer#submitList,其中使用的是 unmodifiable list mReadOnlyListAsyncListDiffer#getCurrentList返回的数据源也是这个,外部是不能修改的)。

但是BRVAH目前的使用中,AsyncListDiffer#submitList使用的是val oldList: List<T> = adapter.data,但是这个adapter.data在外部是可以对数据list进行add/remove之类的操作的。

这样就导致了当前issue的问题,在后台线程进行diff的过程中,其他地方主线程对adapter.data数据源进行add/remove操作之后,后台线程处理中的BrvahAsyncDiffer#submitList中的val oldList: List<T> = adapter.data就被修改了,导致getOldListSize是原先的数据总数,但是oldList#get(index)时是其他地方主线程更新后的数据list,list的数据已经变了,就有可能导致IndexOutOfBoundsException或者其他问题了。

zhujunhua2012 avatar Jan 14 '22 02:01 zhujunhua2012

@limuyang2 @CymChad

zhujunhua2012 avatar Jan 14 '22 02:01 zhujunhua2012

@limuyang2 @CymChad

作者应该已经不维护了😂

SaltedFish-Extreme avatar Jan 21 '22 09:01 SaltedFish-Extreme

同样遇到这样的问题,请问下您解决了没有

extracod avatar Mar 31 '22 01:03 extracod

#setDiffNewData这个使用异步diff BrvahAsyncDiffer#submitList,应该是参考的官方的AsyncListDiffer#submitList。 但是官方的AsyncListDiffer#submitList,其中使用的是 unmodifiable list mReadOnlyListAsyncListDiffer#getCurrentList返回的数据源也是这个,外部是不能修改的)。

但是BRVAH目前的使用中,AsyncListDiffer#submitList使用的是val oldList: List<T> = adapter.data,但是这个adapter.data在外部是可以对数据list进行add/remove之类的操作的。

这样就导致了当前issue的问题,在后台线程进行diff的过程中,其他地方主线程对adapter.data数据源进行add/remove操作之后,后台线程处理中的BrvahAsyncDiffer#submitList中的val oldList: List<T> = adapter.data就被修改了,导致getOldListSize是原先的数据总数,但是oldList#get(index)时是其他地方主线程更新后的数据list,list的数据已经变了,就有可能导致IndexOutOfBoundsException或者其他问题了。

extracod avatar Mar 31 '22 06:03 extracod

这个问题该怎么解决?

2318423730 avatar Dec 26 '22 09:12 2318423730

用這隻就能做同步了 setDiffNewData(@NonNull diffResult: DiffUtil.DiffResult, list: MutableList<T>)

dendrocyte avatar Apr 13 '24 11:04 dendrocyte