java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position

一、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



作者:此号已卸载
链接:https://www.jianshu.com/p/a15764f6d673
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/a243920187/article/details/79377760