You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView调用notifyItemRemoved抛异常,求正确调用时机

问题描述

我开发了一款壁纸APP,通过API获取壁纸分类。在「分类」标签页中,我希望隐藏部分分类板块。理想情况下应由后端处理,但当前后端开发者无法配合,因此我自行实现。

最初我在RecyclerView的onBindViewHolder方法中判断,若分类标题为“Hot”则调用list.removeAt(holder.layoutPosition),但界面未更新;添加notifyItemRemoved(holder.layoutPosition)和notifyItemRangeChanged(holder.layoutPosition, list.size)方法后,出现“Cannot call this method while RecyclerView is computing a layout or scrolling”异常。

请问应在何处调用这些方法以避免该错误?

更新:我已在onResponse方法中通过categories.categories!!.removeAt(5)和categories.categories!!.removeAt(1)移除元素,再初始化RecyclerViewAdapter...

解决方案

嘿,这个问题我之前踩过坑,咱们好好捋捋:

为什么最初的做法会报错?

onBindViewHolder是RecyclerView在布局计算或滚动过程中触发的方法——它正忙着绑定视图、计算每个item的位置呢,这时候你直接修改数据源并调用notify系列方法,相当于硬生生打断它的工作流程,自然会抛出那个异常。而且在这个时机改数据源,还可能导致列表索引混乱,出现布局错位的问题。

最稳妥的解决方式(就是你现在用的这个!)

在拿到API数据之后、初始化RecyclerView Adapter之前完成数据过滤,这才是正确的打开方式:

  • 就像你更新里说的,在onResponse回调里直接对返回的分类列表做移除/过滤操作,比如删掉不需要的第1、第5个元素,确认列表是你想要的状态后,再把处理好的列表传给Adapter并初始化。
  • 这种方式下,Adapter从一开始拿到的就是干净的、已经过滤掉冗余分类的数据源,根本不需要在RecyclerView的绑定阶段去修改数据,完全避开了布局过程中操作数据的风险,代码逻辑也更清晰。

如果后续需要动态移除分类(比如用户操作触发)

要是之后有场景需要在APP运行中动态隐藏分类,那你得确保修改数据源和调用通知方法的时机是在RecyclerView的布局周期之外,比如用recyclerView.post { ... }把操作包裹起来:

// 示例:动态移除目标位置的分类
recyclerView.post {
    yourCategoryList.removeAt(targetPosition)
    yourAdapter.notifyItemRemoved(targetPosition)
}

post方法会把你的任务放到RecyclerView的消息队列里,等它完成当前的布局或滚动操作后再执行,就不会触发那个讨厌的异常了。

内容的提问来源于stack exchange,提问作者Armen Hovhannisian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:54:13