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

Flutter中如何让showDialog等待异步函数执行完再构建组件

Flutter扫码场景异步数据未完成就触发弹窗的空值问题修复

问题现象

  • 已完成二维码扫描基础逻辑开发,扫码触发后拉取关联数据时,弹窗组件构建逻辑提前执行,依赖的业务数据为空导致组件报错
  • 日志打印顺序可验证时序问题:showDialog相关逻辑在异步数据获取函数getQRData()执行完毕前就已触发

原问题代码

数据获取函数

void getQRData() async {
    // Get User Data from ID
    print('qrcode: $qrcode');

    // Take the UserData[Number] to get user short data
    data = await UserDatabase.getUserShortData(
      userId: qrcode,
      phoneNumber: null,
    );

    print('data is : $data');

    await Future.forEach(
        Provider.of<ContactDataProvider>(context, listen: false)
            .getContactConnection
            .keys, (key) async {
      connectedContactData =
          Provider.of<ContactDataProvider>(context, listen: false)
              .getContactConnection[key];
      print(connectedContactData);
      if (connectedContactData['status'] == 'connected' ||
          connectedContactData['status'] == 'sent_req') {
        filteredId.add(connectedContactData['contact_uid']);
        print('filteredId: ${filteredId}');
      }
    });
  }

扫码组件逻辑

Container(
  width: 250,
  height: 250,
  child: ScanView(
    controller: scanController,
    scanAreaScale: 0.8,
    scanLineColor: Colors.red,
    onCapture: (photoData) {
      qrcode = photoData;
      print('qrcode: $qrcode');

      getQRData();

      print(data);
      
      //ShowDialog Widget Code
    },
  ),
)

问题根因

Dart中async标记的函数返回Future对象,调用时如果不添加await关键字,程序不会等待异步任务执行完成,会直接同步执行后续逻辑。当前代码在onCapture回调中直接调用getQRData()未加等待,所以调用后立刻执行后续弹窗逻辑,此时data、filteredId等变量还未完成赋值,自然为空。

修复方案

  1. 将onCapture回调标记为async,调用getQRData()时添加await关键字,强制等待所有数据拉取、处理逻辑执行完成后,再执行弹窗构建逻辑
  2. (可选优化)数据等待过程中添加加载态,异常场景添加错误捕获,避免无反馈或崩溃

最小修复代码

onCapture: (photoData) async { // 回调加async支持异步等待
  qrcode = photoData;
  print('qrcode: $qrcode');

  await getQRData(); // 加await等待数据拉取完成

  print(data);
  // 此处再编写showDialog逻辑,所有依赖变量已完成赋值
  showDialog(
    context: context,
    builder: (context) {
      // 可安全使用data、filteredId等变量构建组件
      return const SizedBox(); // 替换为你的业务弹窗组件
    }
  );
},

带加载态与异常捕获的优化版本

onCapture: (photoData) async {
  qrcode = photoData;
  try {
    // 弹出不可关闭的加载提示
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => const Center(child: CircularProgressIndicator())
    );
    // 等待数据拉取完成
    await getQRData();
    // 关闭加载框
    Navigator.pop(context);
    // 弹出业务结果弹窗
    showDialog(
      context: context,
      builder: (context) => const SizedBox() // 替换为你的业务弹窗组件
    );
  } catch (e) {
    // 异常场景关闭加载框,弹出错误提示
    Navigator.pop(context);
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('获取扫码信息失败,请重试'))
    );
  }
},

注意:getQRData函数如果涉及遍历、多接口请求等耗时操作,必须加加载态避免用户误以为页面无响应。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:45:38