List 颤振/省道:在不更改列表元素的情况下并发修改异常

List 颤振/省道:在不更改列表元素的情况下并发修改异常,list,flutter,dart,List,Flutter,Dart,在测试和调试应用程序的过程中,我注意到有一个异常,通常只在调试测试期间发生,在一个遍历列表的for循环中: [错误:flatter/lib/ui/ui\u dart\u state.cc(177)]未处理的异常:迭代期间的并发修改:“\u growtablelist”的实例(长度:0)。 我四处搜索发现,如果在迭代过程中更改列表本身,这种情况通常会发生,但我看不到它在代码中发生的位置: 主要功能: static Future<void> save(EntryModel entry)

在测试和调试应用程序的过程中,我注意到有一个异常,通常只在调试测试期间发生,在一个遍历列表的for循环中:

[错误:flatter/lib/ui/ui\u dart\u state.cc(177)]未处理的异常:迭代期间的并发修改:“\u growtablelist”的实例(长度:0)。

我四处搜索发现,如果在迭代过程中更改列表本身,这种情况通常会发生,但我看不到它在代码中发生的位置:

主要功能:

static Future<void> save(EntryModel entry) async {
    ...
      List<TagModel> tagsList = entry.tags;
      List<int> tagIdsInserted = [];
      if (tagsList != null && tagsList.isNotEmpty) {
        for (TagModel tag in tagsList) {

          //Error happens inside this loop
          int tagIdInserted = await TagContract.save(tag); //this function does not alter the tag in any way.

          if (tagIdInserted == null || tagIdInserted <= 0) {
            throw Exception('Invalid TagID!');
          }
          tagIdsInserted.add(tagIdInserted);
        }
      }
静态未来保存(EntryModel条目)异步{
...
列表标记列表=entry.tags;
列表tagIdsInserted=[];
if(tagsList!=null&&tagsList.isNotEmpty){
用于(标记列表中的标记模型标记){
//错误发生在这个循环中
int tagIdInserted=await TagContract.save(tag);//此函数不会以任何方式更改标记。

如果(tagIdInserted==null | | tagIdInserted尝试避免在循环中使用
wait
,那太危险了

您必须了解异步代码是如何执行的。如果遇到
等待
,并且
未来
无法同步返回,则运行时将暂停此函数的执行,并跳转到队列顶部的任何其他作业

因此,当遇到
await
时,运行时将开始执行一些天知道的代码,这些代码与您的
tagsList
相接触

尝试理解以下示例。这将直接触发异常

void main(){
列表ID=[1,2,3];
测试(ids);
add(1);//如果异步函数挂起,它将成为队列的顶部。
}
无效测试(列表ID)异步{
用于(id中的最终id){
等待未来。延迟(持续时间(毫秒:10));
}
}
在异步编程中,避免编写依赖于公开共享状态的
wait

对于异步任务列表,请始终在
Iterable
中准备它们,然后使用
Future。等待
同步它们,并在单个
wait
中获得结果

为您的代码

final results=wait Future.wait(tagsList.map((tag)=>TagContract.save(tag)))

TagModel是否持有对其EntryModel的引用?TagContract在保存时做什么?是否有一些模型管理器可能正在清除EntryModel的标记?没有足够的信息来解决此问题。您必须使用调试器来逐步执行代码。@hola否,TagModel不包含对该项的任何引用。错误TagContract将TagModel信息记录在SQLite数据库中。我尝试调试代码,我注意到在第二次或第三次循环迭代中,EntryModel出于某种原因清除了对TagModel列表的引用。我仍然不知道问题的根源是什么,但第一个答案似乎澄清了一些问题。我根据您的建议测试了代码。到目前为止,它似乎可以工作,但我仍然不确定这是否是问题的根源。我将在文档中搜索未来如何工作,但感谢您的建议。Dart的
Future
与Javascript的
Promise
工作方式相同。您可以参考这两个文档操作。最好在
等待
之前准备并使用本地状态,因为
等待
意味着“在这里,运行时调度器可以执行任意其他任务以等待”