RecyclerView and java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder in Samsung devices RecyclerView and java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder in Samsung devices android android

RecyclerView and java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder in Samsung devices


This problem is caused by RecyclerView Data modified in different thread. The best way is checking all data access. And a workaround is wrapping LinearLayoutManager.

Previous answer

There was actually a bug in RecyclerView and the support 23.1.1 still not fixed.

For a workaround, notice that backtrace stacks, if we can catch this Exception in one of some class it may skip this crash. For me, I create a LinearLayoutManagerWrapper and override the onLayoutChildren:

public class WrapContentLinearLayoutManager extends LinearLayoutManager {    //... constructor    @Override    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {        try {            super.onLayoutChildren(recycler, state);        } catch (IndexOutOfBoundsException e) {            Log.e("TAG", "meet a IOOBE in RecyclerView");        }    }}

Then set it to RecyclerView:

RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false));

Actually catch this exception, and seems no any side-effect yet.

Also, if you use GridLayoutManager or StaggeredGridLayoutManager you must create a wrapper for it.

Notice: The RecyclerView may be in a wrong internal state.


This is an example for refreshing data with completely new content.You can easily modify it to fit your needs.I solved this in my case by calling:

notifyItemRangeRemoved(0, previousContentSize);

before:

notifyItemRangeInserted(0, newContentSize);

This is the correct solution and is also mentioned in this post by an AOSP project member.


I faced this issue once, and I solved this by wrapping the LayoutManager and disabling predictive animations.

Here an example:

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;  }}

And set it to RecyclerView:

RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManagerWrapper(context, LinearLayoutManager.VERTICAL, false);