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

RecyclerView+Data Binding滚动后删除位置错误问题求助

RecyclerView滚动后删除条目异常的原因解析

问题现象

  • 用RecyclerView结合DataBinding展示Route列表,测试数据为Route1至Route10,每条条目带删除按钮
  • 未滚动时删除前两项正常,可删除全部条目;滚动后删除会选中错误条目,最终抛出IndexOutOfBoundsException
  • 尝试用absoluteAdapterPosition、adapterPosition、bindingAdapterPosition、layoutPosition替代传入的position参数,问题依旧
  • 参考相关方案后情况改善,但删除最后一条数据时仍出现位置异常
  • 将删除按钮的OnClickListener移至ViewHolder内部后,问题彻底解决

核心原因:RecyclerView视图复用+点击事件的绑定逻辑

RecyclerView的核心特性是ViewHolder复用:当列表滚动时,离开屏幕的ViewHolder会被回收,重新绑定给新进入屏幕的数据。

旧写法失效的本质

如果把点击事件逻辑(尤其是依赖位置的操作)写在onBindViewHolder中,会触发两个致命问题:

  1. 位置值过期:onBindViewHolder的position参数是绑定瞬间的静态位置,当后续列表发生变化(比如删除条目)或ViewHolder被复用时,这个值不会同步更新,点击时用这个旧位置会删除错误条目。
  2. 事件残留:每次onBindViewHolder都会给按钮设置新的点击事件,但旧的事件逻辑可能因为变量捕获机制残留,导致点击时执行的是旧的位置逻辑。

移至ViewHolder内部生效的原因

将点击事件写在ViewHolder的绑定方法里,本质是利用了ViewHolder的生命周期特性:

  1. 实时位置获取:ViewHolder的layoutPosition是当前在RecyclerView中的实时动态位置,每次绑定新数据时都会同步更新,点击时使用这个值能确保拿到当前条目的正确位置。
  2. 逻辑跟随ViewHolder复用:每次ViewHolder被复用时,routeViewHolderBinding会重新执行,点击事件的逻辑也会被重新绑定,确保和当前显示的数据完全匹配。

额外优化建议

不要用notifyDataSetChanged()做全量更新,改用notifyItemRemoved(currentPosition)做局部更新,既能提升性能,也能避免全量刷新带来的位置错乱风险。同时建议在点击时实时获取位置,而非提前赋值:

binding.delete.setOnClickListener {
    val currentPosition = layoutPosition
    // 避免ViewHolder已被回收但事件未销毁的极端情况
    if (currentPosition != RecyclerView.NO_POSITION) {
        routeList.removeAt(currentPosition)
        routeAdapter.notifyItemRemoved(currentPosition)
        saveDataRouteAdapter(routeList)
    }
}

内容的提问来源于stack exchange,提问作者jòckel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:05:17