RecyclerView的bug——Inconsistency detected,recyclerview
bug重現的方法
使用 RecyclerView 加SwipeRefreshLayout下拉重新整理的時候,如果綁定的 List 對象在更新資料之前進行了 clear,而這時使用者緊接著迅速上滑 RecyclerView,就會造成崩潰,而且異常不會報到我們的代碼上,屬於RecyclerView內部錯誤。
可能的原因
當 clear 了 list 之後,這時迅速上滑,而新資料還沒到來,導致 RecyclerView 要更新載入下面的 Item 時候,找不到資料來源了,造成 crash,就會報以下錯誤
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956) at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) at android.view.Choreographer.doCallbacks(Choreographer.java:555) at android.view.Choreographer.doFrame(Choreographer.java:524) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4921) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) at dalvik.system.NativeStart.main(Native Method)
解決方案
在重新整理時,也就是 clear 的同時,讓 RecyclerView 暫時不能夠滑動,之後再允許滑動即可。代碼就是在 RecyclerView 初始化的時候加上是否在重新整理進而攔截手勢,需要一個布爾型變數判斷是否正在重新整理,在重新整理時設定為true,重新整理完畢後設定為false,相關代碼如下
private boolean mIsRefreshing=false;mRecyclerView.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mIsRefreshing) { return true; } else { return false; } } });//當重新整理時設定//mIsRefreshing=true;//重新整理完畢後還原為false//mIsRefreshing=false;
總結
顯然進位滑動不明智,但是在沒找到其他方式解決之前,這也不失為一個辦法。