最近写了一个语音直播间的项目,背包礼物全部送出之后,要删除这一项并且刷新显示,结果在测试中发现了闪退的情况。我竟然在list的foreach中直接进行remove操作,确实有点傻,在这里记录一下。
如图,背包中全部送出之后删除这一项。
错误代码:
var item = allBeen.filter { it.isChecked }.get(0)
adapters.forEach { adapter ->
adapter.data.forEach {
if (it.gift_id.equals(gift_id)) {
it.numbers = it.numbers - number_change * size
//删除的条件(我的是数量为0)
if (it.numbers == 0) {
adapter.data.remove(it)
adapter.notifyDataSetChanged()
}
}
}
adapter.notifyDataSetChanged()
}
正确代码:
var item = allBeen.filter { it.isChecked }.get(0)
adapters.forEach { adapter ->
adapter.data.forEach {
if (it.gift_id.equals(gift_id)) {
it.numbers = it.numbers - number_change * size
}
}
var iterator = adapter.data.iterator()
while (iterator.hasNext()) {
var temp = iterator.next()
//删除的条件(我的是数量为0)
if (temp.numbers == 0) {
iterator.remove()
}
}
adapter.notifyDataSetChanged()
}
阿里编程手册中说:
通俗的解释,在list进行for循环的时候,进行remove操作,list的size减一,但是for循环还在进行,for的size没有更新,那么就会抛出异常。
源码解释,Iterator的remove()的源码如下:
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet); // 调用ArrayList的remove移除元素,且size减1
cursor = lastRet; // 将游标回退一位
lastRet = -1; // 重置lastRet
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
Iterator.remove()在执行集合本身的remove后,同时对游标进行了 “校准”,for循环过程中并没有。
参考 :
https://blog.csdn.net/qq_15509421/article/details/90300039