向列表添加项时触发ConcurrentModificationError问题求助
Flutter ConcurrentModificationError 问题解决思路
在Flutter开发中,点击按钮向收藏列表添加一个或多个漫画时,偶发ConcurrentModificationError错误,报错信息为:Concurrent modification during iteration: Instance(length:7) of '_GrowableList'.,报错位置指向第17行,疑似来自getFavMangas()中的第二个for循环,已尝试5天仍未解决。
问题原因
这个错误核心是遍历列表的同时修改了该列表。你的favMangasListTitle是全局可变列表,当getFavMangas()在遍历它的过程中,如果其他异步操作(比如updateFavMangaList或页面跳转后的状态刷新)同时修改了这个列表,就会触发并发冲突。加上全局列表没有线程安全保护,Flutter的UI线程和异步任务容易同时访问列表导致报错。
解决方案
1. 改用局部变量替代全局列表
把favMangasListTitle和detailledMangaList改成getFavMangas()内部的局部变量,彻底避免外部操作意外修改遍历中的列表:
FirebaseFirestore firestore = FirebaseFirestore.instance; String title = '1'; String read_chapter = '1'; Future<List> getFavMangas() async { var value = await firestore.collection("users/${user.uid}/fav_mangas").get(); final favMangasGetter = value.docs.map((doc) => doc.data()).toList(); // 改为方法内局部变量 List favMangasListTitle = []; List detailledMangaList = []; for (var i in favMangasGetter) { title = i['title']; read_chapter = i['read_chapter']; favMangasListTitle.add(title); } for (var i in favMangasListTitle) { final mangas = await FirebaseFirestore.instance .collection('mangas') .where('title', isEqualTo: i) .get(); final receivedMangaDetailled = mangas.docs.map((doc) => doc.data()).toList(); detailledMangaList.addAll(receivedMangaDetailled); } print(detailledMangaList); return detailledMangaList; }
2. 确保异步操作顺序执行
按钮点击时,updateFavMangaList()是异步函数,你之前没有等待它完成就执行setState和页面跳转,可能导致getFavMangas()在更新未完成时就读取列表,引发冲突。修改按钮事件,等待更新完成后再执行后续操作:
Directionality( textDirection: TextDirection.rtl, child: ElevatedButton.icon( onPressed: () async { // 等待收藏列表更新完成 await updateFavMangaList(); setState(() {}); // 等待页面返回后再刷新状态 await Navigator.push( context, MaterialPageRoute(builder: (context) => MangathequePage()) ); setState(() {}); }, icon: Icon(Icons.arrow_back), label: Text('Suivant'), ), ),
3. 遍历列表时使用副本(保留全局列表的备选方案)
如果必须保留全局的favMangasListTitle,遍历前创建一个列表副本,避免遍历原列表时被外部修改:
// 第二个for循环改为遍历列表副本 for (var i in List.from(favMangasListTitle)) { final mangas = await FirebaseFirestore.instance .collection('mangas') .where('title', isEqualTo: i) .get(); final receivedMangaDetailled = mangas.docs.map((doc) => doc.data()).toList(); detailledMangaList.addAll(receivedMangaDetailled); }
额外优化建议
- 减少全局可变状态的使用,改用
StatefulWidget的本地状态或专门的状态管理库(如Provider、Riverpod)管理收藏列表,从根源避免全局变量带来的并发问题。 updateFavMangaList()开头的get()调用没有实际作用,可以直接删除,简化代码。
内容的提问来源于stack exchange,提问作者Clermoe
相关产品推荐
相关产品推荐

