Flutter条码扫描完成后如何在扫描页中央显示ProgressIndicator并调用API
问题原因
startBarcodeScanStream方法逻辑错误:你监听了条码扫描流,但没有等待流返回结果就直接返回了变量,Future会立即执行完成,FutureBuilder刚渲染就进入了ConnectionState.done状态,自然不会按预期显示加载指示器。- 状态更新逻辑缺失:你没有使用状态变量控制加载指示器的显隐,且在
builder方法中直接调用getGoodsData接口,每次组件重绘都会重复触发接口请求,逻辑不符合要求。 - FutureBuilder使用场景错误:你的需求是「扫描完成后才显示加载、调用接口」,而FutureBuilder是等待异步任务完成后渲染UI,逻辑顺序完全相反。
修复方案
首先将当前组件改为StatefulWidget,按以下逻辑调整代码:
- 定义状态变量控制加载状态、存储扫描结果
- 在
initState中初始化条码扫描流,不要在build方法中初始化扫描逻辑,避免重复创建扫描实例 - 扫描到有效条码后,先更新状态显示加载指示器,再执行接口请求,请求结束后更新状态隐藏加载指示器
- 布局使用Stack层叠加载指示器,扫描界面正常渲染的同时,加载时居中显示指示器
class BarcodeScanPage extends StatefulWidget { const BarcodeScanPage({super.key}); @override State<BarcodeScanPage> createState() => _BarcodeScanPageState(); } class _BarcodeScanPageState extends State<BarcodeScanPage> { // 控制加载指示器显隐 bool _isLoading = false; @override void initState() { super.initState(); _initBarcodeScan(); } Future<void> _initBarcodeScan() async { FlutterBarcodeScanner.getBarcodeStreamReceiver( '#ff6666', 'Cancel', true, ScanMode.BARCODE) .listen((barcode) async { if (!mounted) return; // 扫描取消直接返回 if (barcode == "-1") { Navigator.pop(context); return; } // 扫描到有效条码,显示加载指示器 setState(() { _isLoading = true; }); try { // 调用接口请求商品数据 await getGoodsData(barcode); // 接口请求成功后的逻辑,比如跳转页面、展示数据 } catch (e) { // 接口报错处理逻辑,比如提示用户扫描失败 } finally { // 无论成功失败,都隐藏加载指示器 if (mounted) { setState(() { _isLoading = false; }); } } }); } // 你的接口请求方法 Future<void> getGoodsData(String barcode) async { // 执行你的API请求逻辑 await Future.delayed(const Duration(seconds: 2)); // 模拟接口请求示例 } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( backgroundColor: Colors.transparent, body: Stack( children: [ // 这里替换为你的扫描界面原有布局内容 const Center(child: Text("条码扫描界面", style: TextStyle(color: Colors.white, fontSize: 18),)), // 加载状态为true时显示加载指示器 if (_isLoading) const Center( child: CircularProgressIndicator(), ) ], ), ), ); } }
内容的提问来源于stack exchange,提问作者Vishali
相关产品推荐
相关产品推荐

