Flutter 异步扫码函数执行后如何正确获取变量赋值给文本框
Flutter扫码首次无法正确填入输入框的修复方案
问题根因
你判断的执行时序错位是完全准确的:
scanQR()是带async标记的异步函数,调用后会立刻启动扫码界面,代码不会卡在这行等扫码结束- 按钮的点击回调里,启动
scanQR()之后会立刻执行后续的setState,读取_scanBarcode的值给输入框控制器赋值 - 这时候扫码界面刚弹出,用户还没完成扫码,
_scanBarcode自然还是初始的默认值unknown - 等用户扫码完成,
scanQR()内部拿到结果、更新_scanBarcode的值时,第一次的赋值逻辑早就跑完了,根本读不到最新值 - 等第二次点击按钮触发扫码时,代码会先读取
_scanBarcode——这时候读到的是上一次扫码存下来的结果,因此会出现“第一次扫码无效、第二次才显示正确内容”的现象
可直接落地的修复方法
方法1:将扫码结果的赋值逻辑移入扫码函数内部(推荐)
所有依赖扫码结果的操作,都放到扫码拿到有效返回值之后执行,从根源上避免时序错位:
- 修改
scanQR函数,在拿到扫码结果、执行setState时同步给文本控制器赋值:
Future<void> scanQR() async { String barcodeScanRes; // Platform messages may fail, so we use a try/catch PlatformException. try { barcodeScanRes = await FlutterBarcodeScanner.scanBarcode( '#ff6666', 'Cancel', true, ScanMode.QR); print(barcodeScanRes); } on PlatformException { barcodeScanRes = 'Failed to get platform version.'; } if (!mounted) return; setState(() { _scanBarcode = barcodeScanRes; // 拿到扫码结果后直接给输入框控制器赋值 _codprodController.text = barcodeScanRes; }); }
- 简化按钮的触发逻辑,不需要再单独执行控制器赋值的代码:
onPressed: () { scanQR(); },
方法2:保留原有代码结构,为异步调用添加等待逻辑
如果因为业务模块拆分需要,必须把控制器赋值逻辑留在按钮回调里,就需要显式等待scanQR()完全执行完成,再运行后续的赋值代码:
- 把按钮的
onPressed回调改成带async标记的异步方法 - 给
scanQR()加上await关键字,等扫码全流程走完再执行赋值
修改后的按钮代码如下:
onPressed: () async { // 等待扫码函数完全执行完毕,拿到更新后的_scanBarcode值 await scanQR(); setState(() { _codprodController.text = _scanBarcode; }); },
注意事项
- 不要在触发扫码的同时同步执行读取扫码结果的逻辑,只要是跳过等待异步结果的写法,都大概率出现时序错位
_codprodController.text的更新本身就会驱动输入框组件刷新,不需要额外叠加重复的setState调用- 如果给onPressed加await但忘了标记async,会直接触发Dart语法报错,编写时需要留意方法的异步声明
内容的提问来源于stack exchange,提问作者abrev
相关产品推荐
相关产品推荐

