RecyclerView:不一致检测。无效的项目位置 [英] RecyclerView: Inconsistency detected. Invalid item position

查看:1966
本文介绍了RecyclerView:不一致检测。无效的项目位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的QA检测到的错误:旋转Android设备(Droid的涡轮增压)的时候,下面的RecyclerView相关的事故发生:

  java.lang.IndexOutOfBoundsException:不一致检测。无效的项目位置2(偏移:2).STATE:3

要我来说,它看起来像内部RecyclerView内部错误,因为我不认为这直接通过我们的code引起的任何方式...

有没有人遇到过这个问题?

什么是解决?

一个残酷的解决办法可能是也许是为了捕获该异常,当它发生,并从头开始重新创建RecyclverView实例,以避免留下损坏状态得到。

但是,如果可能的话,我想明白这个问题更好的(也许是从源头上解决这个问题),而不是掩盖它。

该错误是不容易复制,但它是致命的,当它发生。

完整的堆栈跟踪:

 > W / dalvikvm(7546):主题ID = 1:未捕获的异常线程退出(组= 0x41987d40)
    > E / AndroidRuntime(7546):致命异常:主要
    > E / AndroidRuntime(7546):工艺:com.oblong.mezzedroid,PID:7546
    > E / AndroidRuntime(7546):java.lang.IndexOutOfBoundsException:不一致检测。无效的项目位置2(偏移:2).STATE:3
    > E / AndroidRuntime(7546):在android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:3382)
    > E / AndroidRuntime(7546):在android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:3340)
    > E / AndroidRuntime(7546):在android.support.v7.widget.LinearLayoutManager $ LayoutState.next(LinearLayoutManager.java:1810)
    > E / AndroidRuntime(7546):在android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1306)
    > E / AndroidRuntime(7546):在android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1269)
    > E / AndroidRuntime(7546):在android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:523)
    > E / AndroidRuntime(7546):在org.liboid.recycler_view.RecyclerViewContainer$LiLinearLayoutManager.onLayoutChildren(RecyclerViewContainer.java:179)
    > E / AndroidRuntime(7546):在android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1942)
    > E / AndroidRuntime(7546):在android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237)
    > E / AndroidRuntime(7546):在org.liboid.recycler_view.LiRecyclerView.onLayout(LiRecyclerView.java:30)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    > E / AndroidRuntime(7546):在com.oblong.mezzedroid.workspace.content.bins.BinsContainerLayout.onLayout(BinsContainerLayout.java:22)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
    > E / AndroidRuntime(7546):在android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    > E / AndroidRuntime(7546):在android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    > E / AndroidRuntime(7546):在android.view.View.layout(View.java:14946)
    > E / AndroidRuntime(7546):在android.view.ViewGroup.layout(ViewGroup.java:4651)
    > E / AndroidRuntime(7546):在android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2132)
    > E / AndroidRuntime(7546):在android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1872)
    > E / AndroidRuntime(7546):在雄


解决方案

我有一个(可能)相关的问题 - 进入一个RecyclerView活动的新实例,但有一个小的适配器触发此崩溃,我

RecyclerView.dispatchLayout()可以尝试调用 mRecycler.clearOldPositions前拉离报废项目()。其后果存在,在于它是从有职位公共池拉项目heigher比适配器尺寸。

幸运的是,它不仅这一点,如果predictiveAnimations启用,所以我的解决办法是子类GridLayoutManager(LinearLayoutManager有同样的问题,'修复'),并覆盖支持predictiveItemAnimations()返回false:

  / **
 *无predictive动画GridLayoutManager
 * /
私有静态类NpaGridLayoutManager扩展GridLayoutManager {
    / **
     *禁用predictive动画。有一个在RecyclerView一个bug,导致该意见
     *正在重新加载从当内部回收堆拉无效ViewHolders
     *适配器尺寸有所减少,因为ViewHolder被回收。
     * /
    @覆盖
    公共布尔支持predictiveItemAnimations(){
        返回false;
    }    公共NpaGridLayoutManager(上下文的背景下,ATTRS的AttributeSet,诠释defStyleAttr,诠释defStyleRes){
        超(背景下,ATTRS,defStyleAttr,defStyleRes);
    }    公共NpaGridLayoutManager(上下文的背景下,诠释spanCount){
        超(背景下,spanCount);
    }    公共NpaGridLayoutManager(上下文的背景下,诠释spanCount,诠释取向,布尔reverseLayout){
        超级(上下文,spanCount,取向,reverseLayout);
    }
}

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

这篇关于RecyclerView:不一致检测。无效的项目位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆