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

Flutter中Finish按钮调用reset()与pushNamed()引发并发迭代修改错误

Flutter 发票扫描页面导航后二次扫描报错的修复方案

问题根源分析

你遇到的Concurrent modification during iteration错误,本质是在遍历列表的同时修改了该列表。两种导航方式的差异在于:

  • 连续三次Navigator.pop()会把扫描页面从导航栈中彻底移除,页面的dispose()方法触发,所有监听SupplierModel列表的资源被释放,此时调用reset()修改列表不会有冲突。
  • 用Navigator.pushNamed()时,原扫描页面并未被销毁,仍存活在导航栈中(比如栈结构为Home → Scan → Result → Home),如果扫描页面还在监听SupplierModel的列表变化,此时调用reset()直接修改列表,就会和扫描页面中正在进行的列表遍历操作(比如UI渲染、扫描逻辑中的循环)产生并发冲突。

具体修复步骤

1. 确保扫描页面彻底释放监听资源

在扫描页面的dispose()方法中,取消所有与SupplierModel列表相关的订阅(比如StreamSubscription、ValueListenableSubscription):

class ScanPage extends StatefulWidget {
  @override
  _ScanPageState createState() => _ScanPageState();
}

class _ScanPageState extends State<ScanPage> {
  StreamSubscription? _listSubscription;

  @override
  void initState() {
    super.initState();
    // 假设SupplierModel有列表变化的流监听
    _listSubscription = SupplierModel.instance.listStream.listen((_) {
      // 处理列表变化逻辑
    });
  }

  @override
  void dispose() {
    _listSubscription?.cancel(); // 取消订阅,释放关联资源
    super.dispose();
  }
}

2. 安全修改SupplierModel的列表

不要直接修改原列表,而是替换为新列表,避免遍历中的并发冲突。如果SupplierModel是ChangeNotifier类型,修改reset()方法:

class SupplierModel extends ChangeNotifier {
  List<Item> _items = [];

  void reset() {
    // 替换为新列表,而非直接清空原列表
    _items = [];
    notifyListeners();
  }
}

如果必须修改原列表,可通过Future.microtask延迟修改,确保当前遍历操作完成后再执行:

void reset() {
  Future.microtask(() {
    _items.clear();
    notifyListeners();
  });
}

3. 调整导航逻辑,清理旧页面

用Navigator.pushNamedAndRemoveUntil代替pushNamed,将扫描相关的页面从导航栈中移除,确保旧页面彻底销毁:

// Finish按钮点击逻辑
onPressed: () {
  SupplierModel.instance.reset();
  Navigator.pushNamedAndRemoveUntil(
    context,
    '/home',
    (route) => route.isFirst, // 仅保留首页在栈中
  );
},

4. 排查扫描逻辑中的遍历操作

检查扫描页面中是否存在在UI渲染(比如ListView.builder)或扫描处理逻辑中遍历SupplierModel列表的代码,确保这些遍历操作使用列表的不可变副本:

// 错误示例:直接遍历原列表
for (var item in SupplierModel.instance.items) {
  // 处理逻辑
}

// 正确示例:使用副本遍历
var itemsCopy = List.from(SupplierModel.instance.items);
for (var item in itemsCopy) {
  // 处理逻辑
}

内容的提问来源于stack exchange,提问作者Yogev Arye

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:47:19