Android中如何从Adapter删除多个选中位置的条目?
问题分析与解决方案
错误原因
你的代码存在两个关键问题:
- 误用循环索引
i作为items的删除位置,而非传入的listOfDeleteItemPosition中的目标位置,这直接导致删除的位置完全不符合预期。 - 即便修正为使用
listOfDeleteItemPosition[i],删除元素后后续元素的索引会整体前移,导致原始位置失效。比如先删位置1,原本的位置7会变成6,此时再删7就会操作错误的元素,甚至触发索引越界异常。
正确实现方式
方式一:从后往前删除(推荐,保留删除动画)
核心思路是先将待删除位置按降序排序,从最大的位置开始删除,这样前面的元素位置不会因后续删除而变动,确保每个位置都是当前列表的有效索引。
修正后的代码:
override fun removeDataAtPosition(listOfDeleteItemPosition: ArrayList<Int>) { // 对位置列表降序排序,确保从后往前删除 listOfDeleteItemPosition.sortDescending() for (position in listOfDeleteItemPosition) { // 边界判断,避免索引越界 if (position in 0 until items.size) { items.removeAt(position) notifyItemRemoved(position) } } }
方式二:批量过滤保留元素(简洁,无逐行动画)
如果不需要单个条目的删除动画,可以直接过滤出需要保留的元素,替换原列表后刷新:
override fun removeDataAtPosition(listOfDeleteItemPosition: ArrayList<Int>) { val removeSet = listOfDeleteItemPosition.toHashSet() val newItems = items.filterIndexed { index, _ -> !removeSet.contains(index) } val oldSize = items.size items.clear() items.addAll(newItems) // 通知RecyclerView数据变化,也可以用notifyDataSetChanged() notifyItemRangeRemoved(0, oldSize - newItems.size) }
两种方式对比
- 方式一:逐个删除并调用
notifyItemRemoved,能触发RecyclerView的删除动画,用户体验更好,适合需要动画的场景。 - 方式二:批量更新列表,代码更简洁,但没有单个条目的删除动画,适合对动画无要求的批量操作场景。
内容的提问来源于stack exchange,提问作者MARSH
相关产品推荐
相关产品推荐

