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
相关产品推荐
相关产品推荐

