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

QRViewController扫码重复返回结果 如何实现二维码仅单次扫描

Flutter qr_code_scanner 单次扫码重复触发问题修复

问题根因

从运行日志可以明确原因:pauseCamera()是异步操作,相机硬件关闭、预览停止存在时间差;且条码解码运行在独立的DecoderThread线程,在调用暂停相机前,已经有连续两帧包含二维码的画面被送进了解码队列,哪怕后续相机已经关闭,队列里已经完成解码的结果依然会推送到scannedDataStream流中触发listen回调,最终出现两次相同的扫码结果。
原有代码先await controller.pauseCamera()再处理结果,反而拉长了空窗期,给了第二个解码结果触发回调的机会。

修复方案

不要完全依赖相机暂停操作拦截重复扫码,在业务层增加拦截标记是最稳定的方案:

  • 在扫码页面的状态类中增加布尔类型的拦截标记,初始值设为false,用来标记是否已经处理过当前扫码结果
  • 进入流监听回调的第一时间先判断标记值,如果已经处理过扫码结果直接return,不执行任何后续逻辑
  • 第一次触发回调时立刻把标记设为true,不需要等待相机暂停完成,从入口堵截重复事件
  • 异步执行相机暂停操作,再运行扫码结果处理逻辑
  • 如果后续需要恢复扫码(比如从结果页返回扫码页、需要连续扫多个码),在重新启动相机预览前把拦截标记重置为false即可

修复后参考代码

// 页面State类中增加拦截标记
bool _hasHandledScan = false;

StreamSubscription<Barcode> qrListener(
    QRViewController controller, BuildContext context) {
  return controller.scannedDataStream.listen((event) async {
    // 第一时间拦截重复结果
    if (_hasHandledScan) return;
    // 立刻标记为已处理,不等待相机暂停完成
    _hasHandledScan = true;
    
    // 异步执行相机暂停,无需await阻塞流程
    controller.pauseCamera();
    
    String? url = event.code;
    log('$url');
    // 后续编写自定义扫码结果处理逻辑
  });
}

额外说明

如果业务需要连续扫码(扫完一个码不退出页面,自动准备扫下一个),只需要在单条扫码结果处理完成后,把_hasHandledScan重置为false,再调用controller.resumeCamera()即可,同样可以避免同个二维码被连续识别多次的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:09:44