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

Flutter扫描条形码/二维码后页面关闭无法弹出对话框如何解决?

问题原因分析
    1. 异步扫描方法getBarcodeData错误放置在build树中,该方法返回的是Future而非Widget,不符合Flutter的build规范,且页面每次重绘都会重复触发扫描逻辑,导致页面状态异常。
    1. onWillPop回调返回null,违反了WillPopScope要求返回Future<bool>的规范,系统默认会执行页面关闭逻辑,同时回调内部连续两次调用Navigator.pop也会额外触发页面关闭。
    1. 扫描完成后未等待接口请求完成就执行了页面关闭相关逻辑,导致弹窗无法在当前页显示。
修复步骤

1. 调整扫描逻辑触发时机

将扫描逻辑从build树中移除,改为页面初始化完成后触发:

@override
void initState() {
  super.initState();
  // 等待页面渲染完成后再触发扫描
  WidgetsBinding.instance.addPostFrameCallback((_) => getBarcodeData());
}

修改build方法的Stack子组件,替换为你需要的页面UI元素,不要再调用getBarcodeData()作为子组件。

2. 修复WillPopScope逻辑

修正onBackPress方法的返回值,移除多余的pop调用:

Future<bool> onBackPress() async {
  String imageUrl = StorageUtil.getString('imageurl');
  String strBussName = StorageUtil.getString('buss_name');
  String strName = StorageUtil.getString('name');
  Navigator.pop(context);
  Navigator.of(context).push(MaterialPageRoute(
      builder: (context) => MainActivity(imageUrl, strName, strBussName)));
  // 必须返回bool值,true表示允许当前页面关闭
  return true;
}

3. 优化扫码逻辑,请求完成后弹窗

修改getBarcodeData方法,判断用户取消扫码的场景,等待接口请求完成后再弹出对话框:

getBarcodeData() async {
  try {
    final qrcoder = await FlutterBarcodeScanner.scanBarcode(
        '#ff6666', '取消', true, ScanMode.QR);
    if (!mounted) return;
    // 拦截用户点击取消扫码的场景
    if (qrcoder == '-1') {
      // 如需保留在当前页可不做处理,需要返回上一页则执行Navigator.pop(context)
      return;
    }
    barcodeScanner = qrcoder;
    if (barcodeScanner.isNotEmpty) {
      // 等待接口请求完成
      await getGoodsData(barcodeScanner);
      // 页面未销毁的情况下弹出对话框
      if (mounted) {
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: const Text('操作成功'),
            content: Text('扫描到数据:$barcodeScanner'),
            actions: [
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text('确定'),
              )
            ],
          ),
        );
      }
    }
  } catch (error) {
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('扫码失败:${error.toString()}'))
      );
    }
  }
}

额外注意项

  • 确保getGoodsData方法为异步方法,内部没有执行关闭当前页面的逻辑。
  • 如果你使用自定义扫描UI而非插件自带的扫描页,可调整扫描逻辑为持续扫描,避免单次扫描后自动停止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 16:18:03