调用RecyclerView的notifyItemRemoved方法触发不一致检测异常
嘿,这个问题我之前也踩过坑!那个IndexOutOfBoundsException: Inconsistency detected异常,本质就是RecyclerView的数据源和它内部维护的状态对不上号了,大概率是多线程操作、动画冲突或者布局配置的问题。结合你的代码和日志,给你几个针对性的解决方案:
1. 务必在主线程里修改数据+调用notify方法
RecyclerView的所有数据修改和适配器通知操作,必须在主线程执行!要是你的删除操作是在子线程(比如网络请求回调、后台任务)里触发的,一定要切换到主线程再操作:
runOnUiThread(new Runnable() { @Override public void run() { feedDetailList.remove(position); feedAdapter.notifyItemRemoved(position); // 要是删除后后面的列表项有位置相关的逻辑,加上这句更新后续项的状态 feedAdapter.notifyItemRangeChanged(position, feedDetailList.size() - position); } });
2. 排查有没有并发修改数据源的情况
如果还有其他地方在同时修改feedDetailList(比如下拉刷新、加载更多),就会导致数据源和RecyclerView预期的状态不匹配。建议给数据源加个锁,或者用线程安全的集合比如CopyOnWriteArrayList,要么就确保所有修改数据源的操作都是串行执行的。
3. 别在RecyclerView动画跑的时候改数据
要是你的RecyclerView开了默认的删除动画,动画执行过程中修改数据源很容易搞乱状态。可以先临时关掉动画,改完数据再开回来:
// 先关闭动画 recyclerView.getItemAnimator().setSupportsChangeAnimations(false); // 修改数据并通知 feedDetailList.remove(position); feedAdapter.notifyItemRemoved(position); // 要是需要动画,再重新开启 recyclerView.getItemAnimator().setSupportsChangeAnimations(true);
4. 检查LinearLayoutManager的配置
日志里显示用的是LinearLayoutManager,如果RecyclerView的高度设成了wrap_content,在某些Android版本上容易触发这个异常。可以试试把RecyclerView的高度改成match_parent,或者给布局管理器加个配置:
LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setAutoMeasureEnabled(true); recyclerView.setLayoutManager(layoutManager);
5. 应急方案:用notifyDataSetChanged替代notifyItemRemoved
虽然这个方法效率不高(会刷新整个列表),但如果上面的方案都没解决问题,可以先临时用这个来强制同步状态:
feedDetailList.remove(position); feedAdapter.notifyDataSetChanged();
优先排查多线程的问题哦,这是最常见的诱因!要是确定是在主线程操作,再去检查动画和布局的配置。
内容的提问来源于stack exchange,提问作者Om Infowave Developers

