I have an RxJava2 Observable that takes two lists, calculate diff result for them and send this data to adapter. Adapter dispatch updates on Main Thread.
Code of dispatching in adapter:
public void dispatchStreams(List<StreamV3> streams, @Nullable DiffUtil.DiffResult diffResult) {
if (streams == null) return;
streamsList.clear();
streamsList.addAll(streams);
if (diffResult != null) {
diffResult.dispatchUpdatesTo(this);
}
}
I've got 'Inconsistency detected. Invalid view holder adapter positionViewHolder' error sometime on some devices. And I can't figure out what's wrong with my code. Min SDK 21, Target SDK 26, RecyclerView version is 26.0.0. I know about workaround with extending LinearLayoutManager and silently catching this error but this is bad solution and I believe here should be better one.
Could anyone provide any help please?
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)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With