DiffResult dispatching lead to 'Inconsistency detected. Invalid view holder adapter positionViewHolder' error sometimes
I found a solution for this issue in this answer
It seems that issue is caused by supportsPredictiveItemAnimations property on layout managers. When I set it to false no crash happens anymore.
public class LinearLayoutManagerWrapper extends LinearLayoutManager {
public LinearLayoutManagerWrapper(Context context) {
super(context);
}
public LinearLayoutManagerWrapper(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public LinearLayoutManagerWrapper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean supportsPredictiveItemAnimations() {
return false;
}
}
Got into this issue while writing a Rx RV Diff to run in the background thread. Setting the supportsPredictiveItemAnimations to false is a workaround that prevents the crash but does not really solve the problem.
What was causing this exception on my case was the mutation of the data set in the background thread.
// Diff and update the RV asynchronously
fun update(list: List<D>) {
Observable
.create<Pair<List<D>, DiffUtil.DiffResult>> {
// runs it asynchronous
val result = DiffUtil.calculateDiff(
diffCallback.apply {
newList = list
}
)
it.onNext(Pair(diffCallback.newList, result))
it.onComplete()
}
.takeUntil(destroyObservable) // observe the Lifecycle of the Frag
.subscribeOn(Schedulers.computation()) // run it async
.observeOn(AndroidSchedulers.mainThread()) // jump to the main thread
.subscribe {
// Set the new list
dataSet = it.first.map { it }
it.second.dispatchUpdatesTo(this@ListComponentAdapter)
}
}