PagedListAdapter 删除最后一条数据数组越界

前言

老板说我写的程序崩溃,在删除最后一条数据时。听到这个消息,我很紧张,立马去分析。

日志

日志错误信息如下:

   --------- beginning of crash
2019-10-18 18:13:19.670 19042-19042/com.meichuang.meipian E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.meichuang.meipian, PID: 19042
    java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{d7f30d7 position=0 id=-1, oldPos=1, pLpos:1 scrap [attachedScrap] update tmpDetached no parent} android.support.v7.widget.RecyclerView{20a3a64 VFED..... ......I. 0,175-1080,1109 #7f090217 app:id/recycler_view}, adapter:[email protected]d7f696f, layout:[email protected], context:[email protected]
        at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5610)
        at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5792)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2232)
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1559)
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1519)
        at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:614)
        at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3763)
        at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3219)
        at android.view.View.measure(View.java:23466)
        at android.support.constraint.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
        at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
        at android.view.View.measure(View.java:23466)
        at android.support.constraint.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
        at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
        at android.view.View.measure(View.java:23466)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6834)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:23466)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6834)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1565)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:847)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:726)
        at android.view.View.measure(View.java:23466)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6834)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:847)
        at android.view.View.measure(View.java:23466)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2954)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1753)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2041)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1636)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7946)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1092)
        at android.view.Choreographer.doCallbacks(Choreographer.java:893)
        at android.view.Choreographer.doFrame(Choreographer.java:812)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
        at android.os.Handler.handleCallback(Handler.java:907)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:216)
        at android.app.ActivityThread.main(ActivityThread.java:7625)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)

我去,这是啥情况,更本没有我写的代码的提示,里面的包名都是android系统的,出问题的地方不在我的代码里面。这就悲剧了!

还好,我通过google搜索错误类型,发现有一篇文章解决了这个问题,并且分析了问题的原因。是因为adapter旧的数据和待更新的数据存在差异,导致更新的时候出错。

我们使用的是捕获异常方法;我们重新的LinearLayoutManager如下:

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

public class ExceptionCatchLinearLayoutManager extends LinearLayoutManager {
    public ExceptionCatchLinearLayoutManager(Context context) {
        super(context);
    }

    public ExceptionCatchLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public ExceptionCatchLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

总结

刚开始的时候以为是数据没有正确传入,所以耽误了很多时间。所以以后如果问题不明确的情况下,要立马去搜索相关信息,可能别人也遇到过这个问题。

点赞