RecyclerView内部BUG: java.lang.Ind

作者: 此号已卸载 | 来源:发表于2017-07-17 14:51 被阅读3343次

    一、BUG出现的日志:
    1.情况描述:
    项目刚更新了一个小版本,新增了一个上拉刷新和下拉加载的页面,因为原来的RecyclerView的刷新框架我觉着不好,于是就换了一个,然后在对RCView数据处理的时候,处理的方式和以前是一样的,在测试机上测试也未出现BUG,但是上线之后,爆出了BUG,而且影响人数还很多,于是赶紧查了一下,出现的BUG的相关原因,并解决了它。附上:BUG的Log

    java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 150(offset:150).state:153
        at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5504)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551)
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
        at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
        at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3583)
        at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3312)
        at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1618)
        at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4702)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:619)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:7409)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
    
    

    2.BUG出现的原因:
    因为由崩溃LOG看,属于RcyclerView使用出现的bug,经过多次google相关,总结出了原因:
    就是在进行数据移除和数据增加时,务必要保证Adapter中的数据和移除的数据保持一致!这是什么意思呢?就是如果你更新你的集合后,调用Adapter的新出现的notifyxxxx方法时,adapter 的更新预期结果和实际集合更新结果不同,那么就会出现异常了。
    例如: 比如你集合remove了两条数据,但是你Adapter只notifyItemRemoved(2)(这里表示移除第三条数据,只移除了一条),这种情况旧属于数据不一致了。还有一种是你增加数据,你集合增加10条数据,但是你Adapter的notify只增加了5条数据,这也是数据不一致。
    好了,通过以上两种情况,大概就知道了,这个数据一致其实说的是要保证数量一致。就是说Adapter有个size,你的集合有个size。这两个size,在调用Adapter的notifyxxxx时候必须保持相同。
    看到此处,你应该明白了吧!
    3.解决方案:
    网上有很多解决此类的方案,我择优选择了最靠谱的解决方案,就是复写LinearLayoutManager这个类,代码如下:

    public class RecyclerViewNoBugLinearLayoutManager extends LinearLayoutManager {
        public RecyclerViewNoBugLinearLayoutManager(Context context) {
            super( context );
        }
    
        public RecyclerViewNoBugLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super( context, orientation, reverseLayout );
        }
    
        public RecyclerViewNoBugLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super( context, attrs, defStyleAttr, defStyleRes );
        }
    
        @Override
        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            try {
            //try catch一下
                super.onLayoutChildren( recycler, state );
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    这样就有效避免了解决RecyclerView可能出现的holder数组越界Bug。

    下面几篇文章,是另外几篇关于此BUG的处理。
    https://stackoverflow.com/questions/30458640/recyclerview-java-lang-indexoutofboundsexception-inconsistency-detected-inval
    http://www.cnblogs.com/fuyaozhishang/p/6991221.html

    相关文章

      网友评论

      • xwp:LinearLayoutManager,如果用其他的Manager是否也要trycatch.
        由数据不同步引起,那么在平时写代码的时候同步一下就好了,主要是remove才会越界,所以就remove后立马notify.可能会损下性能.
        xwp:https://blog.csdn.net/user11223344abc/article/details/77148166 这个可以
      • 卜俊文:谢谢楼主~已解决问题。
      • YbSTGing:我也碰到这个问题了,搜索了一下,好多人都是抄一些原理什么的,解决方案都没有:sweat: ,还在楼主的方法靠谱,十分感谢:+1:
      • xljx:支持库DiffUtil进行集合前后差异比较
      • 小学生家长:大神太喜欢你了
        小学生家长:@Yinjihao 嗯嗯 ,按照楼主的方法解决了
        此号已卸载:你也遇到了吗

      本文标题:RecyclerView内部BUG: java.lang.Ind

      本文链接:https://www.haomeiwen.com/subject/dunfkxtx.html