RecyclerView快速上下滑动,crash原因分析及解决
- 异常日志:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position
--------- beginning of crash
05-31 16:03:37.218 E/AndroidRuntime(21081): FATAL EXCEPTION: main
05-31 16:03:37.218 E/AndroidRuntime(21081): Process: com.xxx.xxx, PID: 21081
05-31 16:03:37.218 E/AndroidRuntime(21081): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 9(offset:9).state:12 com.xxx.ugc.feeds.widget.ExtendedRecyclerView{13be059 VFED..... ........ 0,0-1440,2235 #7f0a12ca app:id/recyclerView}, adapter:com.xxx.ugc.feeds.widget.ExtendedRecyclerView$HeaderViewListAdapter@2d7ce9f, layout:com.xxx.ugc.feeds.view.adapter.RecyclerViewNoBugLinearLayoutManager@4d19bec, context:com.xxx.xxxhd.home.ui.MainActivity@1ca5c38
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5923)
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:366)
05-31 16:03:37.218 E/AndroidRuntime(21081): at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:397)
05-31 16:03:37.218 E/AndroidRuntime(21081): at android.os.Handler.handleCallback(Handler.java:938)
05-31 16:03:37.218 E/AndroidRuntime(21081): at android.os.Handler.dispatchMessage(Handler.java:99)
05-31 16:03:37.218 E/AndroidRuntime(21081): at android.os.Looper.loop(Looper.java:223)
05-31 16:03:37.218 E/AndroidRuntime(21081): at android.app.ActivityThread.main(ActivityThread.java:7664)
05-31 16:03:37.218 E/AndroidRuntime(21081): at java.lang.reflect.Method.invoke(Native Method)
05-31 16:03:37.218 E/AndroidRuntime(21081): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(
- 复现场景
在使用SwipeRefreshLayout 嵌套 RecyclerView场景,页面支持下拉刷新(Refresh)和上滑加载更多(LoadMore)。
先快速下拉刷新页面,然后快速上滑到页面最后触发加载更多操作,此时页面有2个loading,一个是刷新loading,一个是加载更多loading。此时极容易出现上面的crash即: IndexOutOfBoundsException: Inconsistency detected. Invalid item position
- 问题分析
下拉刷新时,会把数据集(ArrayList)清空,执行Clear操作。
上滑加载更多时,会向数据集里添加数据。
清空数据的时候,没有执行 notifyDataSetChanged 会导致该问题
4. 解决方案
清空数据的时候,需要执行 notifyDataSetChanged 操作通知Adapter数据集已经更改。否则Adapter 不知道数据集已经更改,位置计算就有问题。
代码可参考:
dataList.clear();
notifyDataSetChanged();