解决java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionV

解决java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder

bug日志:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{ecef223 position=46 id=-1, oldPos=-1, pLpos:-1 no parent} android.support.v7.widget.RecyclerView{9876d9c VFED… … 0,0-1052,1651 #7f100210 app:id/recyclerView}, adapter:net.liexiang.dianjing.adapter.AdapterFeatureListRv@4b763a5, layout:android.support.v7.widget.LinearLayoutManager@90fe37a, context:net.liexiang.dianjing.ui.order.feature.FeatureListActivity@95fa84
at android.support.v7.widget.RecyclerView R e c y c l e r . v a l i d a t e V i e w H o l d e r F o r O f f s e t P o s i t i o n ( R e c y c l e r V i e w . j a v a : 5610 ) a t a n d r o i d . s u p p o r t . v 7. w i d g e t . R e c y c l e r V i e w Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5610) at android.support.v7.widget.RecyclerView Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5610)atandroid.support.v7.widget.RecyclerViewRecycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5792)
at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:285)
at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:342)
at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:358)
at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:365)
at android.support.v7.widget.GapWorker.run(GapWorker.java:396)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6806)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

原因:

通过查阅官方论坛和网上资料,基本锁定为RecyclerView官方的BUG

解决方式:

方式一:

继承封装LinearLayoutManager类,重写onLayoutChildren()方法,try-catch捕获该异常。

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

/**

  • Created by fx on 2019/9/11.
    */
    public class XLinearLayoutManager extends LinearLayoutManager {

    public XLinearLayoutManager(Context context) {
    super(context);
    }

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

    public XLinearLayoutManager(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 (IndexOutOfBoundsException e) {
    Log.e(“bug”, “crash in RecyclerView”);
    }
    }

}

LinearLayoutManager mLayoutManager=new XLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLayoutManager);

方式二:

数据变动(移除和增加),执行同步操作时,要保证RecyclerView的Adapter中的数据与需要同步的外部集合数据数量一致!
即每一次外部数据变动(移除和增加)时,都需主动Adapter做一次数据同步操作。以避免数据同步时内外数据不一致

数据同步方法:
notifyItemRangeRemoved();
notifyItemRangeInserted();
notifyItemRangeChanged();
notifyDataSetChanged();

异常代码:
public void setData(List list) {
if (list != null ) {
array.clear();
array.addAll(list);
notifyItemRangeChanged(0, list.size());
}
}

这里对该外部数据做了两个操作:先移除数据,然后添加数据,之后notify数据集。
array.addAll(list)时,Adapter的内部数据还处在array.clear()之前的状态,造成了Adapter内外数据不一致。

修复代码:
public void setData(List list) {
if (list != null ) {
int size = array.size();
array.clear();
notifyItemRangeRemoved(0, size);
array.addAll(list);
notifyItemRangeChanged(0, list.size());
}
}

我是用的是第一种方法,只要考虑到第二种方法在数据频繁变动时需要频繁进行同步操作。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值