最近在线上发现了一个问题,但是并没有出现错误的具体位置,错误是这样的:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 2(offset:2).state:11at
android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5512)
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:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)at android.app.ActivityThread.main(ActivityThread.java:5446)
at java.lang.reflect.Method.invoke(Native Method)at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:736)
看着像是RecyclerView的问题,但是也没报具体错误职位,不太懂这是什么意思,于是就上网百度了一下说这是RecycleView内部错误
RecyclerView 存在的一个明显的 bug 一直没有修复:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position…
重现的方法是:使用 RecyclerView 加官方下拉刷新的时候,如果绑定的 List 对象在更新数据之前进行了 clear,而这时用户紧接着迅速上滑 RV,就会造成崩溃,而且异常不会报到你的代码上,属于RV内部错误。初次猜测是,当你 clear 了 list 之后,这时迅速上滑,而新数据还没到来,导致 RV 要更新加载下面的 Item 时候,找不到数据源了,造成 crash.
在网上看到的解决方法有两个:
1.
就是在刷新,Recyclerview clear的同时让Recyclerview不能滑动,这样的解决办法也是可以的,可以避免错误的发生,但是我总感觉这样的会影响用户的体验,该解决办法的代码如下:
mRecyclerView.setOnTouchListener(
new
View.OnTouchListener() {
@Override
public
boolean
onTouch(View v, MotionEvent event) {
if
(mIsRefreshing) {
return
true
;
}
else
{
return
false
;
}
}
}
);
|
然后去改变和恢复 mIsRefreshing 这个 boolean 即可。
2.
我们写一个MyLinearLayoutManager去继承LinearLayoutManager,在出现问题的时候我们catch了,这样的处理方法我觉得还是可以的,具体实现如下:
public class MyLinearLayoutManager extends LinearLayoutManager {
public MyLinearLayoutManager(Context context) {
super(context);
}
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public MyLinearLayoutManager(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) {
e.printStackTrace();
}
}
}
标注的地方是主要实现代码
mRecyclerView.setLayoutManager(new MyLinearLayoutManager(this));
我是使用的第二种方式,如果还有别的方式也请告知一下,这里记录一下,日后也会用到,感谢那些无私奉献的人。