Our QA has detected a bug: when rotating the Android device (Droid Turbo), the following RecyclerView-related crash happened:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:3
To me, it looks like an internal error inside RecyclerView, as I can't think of any way of this being caused directly by our code...
Has anyone encountered this problem?
What would be the solution?
A brutal workaround could be perhaps to catch the exception when it happens and re-create the RecyclverView instance from scratch, to avoid getting left with a corrupted state.
But, if possible, I would like to understand the problem better (and perhaps fix it at its source), instead of masking it.
The bug is not easy to reproduce, but it is fatal when it happens.
The full stack-trace:
W/dalvikvm( 7546): threadid=1: thread exiting with uncaught exception (group=0x41987d40) E/AndroidRuntime( 7546): FATAL EXCEPTION: main E/AndroidRuntime( 7546): Process: com.oblong.mezzedroid, PID: 7546 E/AndroidRuntime( 7546): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:3 E/AndroidRuntime( 7546): at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3382) E/AndroidRuntime( 7546): at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3340) E/AndroidRuntime( 7546): at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1810) E/AndroidRuntime( 7546): at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1306) E/AndroidRuntime( 7546): at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1269) E/AndroidRuntime( 7546): at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:523) E/AndroidRuntime( 7546): at org.liboid.recycler_view.RecyclerViewContainer$LiLinearLayoutManager.onLayoutChildren(RecyclerViewContainer.java:179) E/AndroidRuntime( 7546): at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1942) E/AndroidRuntime( 7546): at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237) E/AndroidRuntime( 7546): at org.liboid.recycler_view.LiRecyclerView.onLayout(LiRecyclerView.java:30) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) E/AndroidRuntime( 7546): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) E/AndroidRuntime( 7546): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) E/AndroidRuntime( 7546): at com.oblong.mezzedroid.workspace.content.bins.BinsContainerLayout.onLayout(BinsContainerLayout.java:22) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) E/AndroidRuntime( 7546): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) E/AndroidRuntime( 7546): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) E/AndroidRuntime( 7546): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) E/AndroidRuntime( 7546): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) E/AndroidRuntime( 7546): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525) E/AndroidRuntime( 7546): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) E/AndroidRuntime( 7546): at android.widget.FrameLayout.onLayout(FrameLayout.java:388) E/AndroidRuntime( 7546): at android.view.View.layout(View.java:14946) E/AndroidRuntime( 7546): at android.view.ViewGroup.layout(ViewGroup.java:4651) E/AndroidRuntime( 7546): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2132) E/AndroidRuntime( 7546): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1872) E/AndroidRuntime( 7546): at andro
I had a (possibly) related issue - entering a new instance of an activity with a RecyclerView, but with a smaller adapter was triggering this crash for me.
RecyclerView.dispatchLayout()
can try to pull items from the scrap before calling mRecycler.clearOldPositions()
. The consequence being is that it was pulling items from the common pool that had positions higher than the adapter size.
Fortunately, it only does this if PredictiveAnimations
are enabled, so my solution was to subclass GridLayoutManager
(LinearLayoutManager
has the same problem and 'fix'), and override supportsPredictiveItemAnimations()
to return false :
/** * No Predictive Animations GridLayoutManager */ private static class NpaGridLayoutManager extends GridLayoutManager { /** * Disable predictive animations. There is a bug in RecyclerView which causes views that * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the * adapter size has decreased since the ViewHolder was recycled. */ @Override public boolean supportsPredictiveItemAnimations() { return false; } public NpaGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public NpaGridLayoutManager(Context context, int spanCount) { super(context, spanCount); } public NpaGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { super(context, spanCount, orientation, reverseLayout); } }
In my case (delete/insert data in my data structure) I needed to clear recycle pool and then notify data set changed!
mRecyclerView.getRecycledViewPool().clear(); mAdapter.notifyDataSetChanged();
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