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

Flutter mobile_scanner扫码后黑屏问题求助

解决方案与问题解答

核心修复方案:正确管理相机控制器生命周期

1. 规范控制器初始化与资源释放

避免扫码后黑屏的关键是确保相机资源被彻底释放,同时避免启动/停止逻辑冲突。以下是可直接复用的实现代码:

class BarcodeScannerPage extends StatefulWidget {
  const BarcodeScannerPage({super.key});

  @override
  State<BarcodeScannerPage> createState() => _BarcodeScannerPageState();
}

class _BarcodeScannerPageState extends State<BarcodeScannerPage> {
  late final MobileScannerController _controller;

  @override
  void initState() {
    super.initState();
    // 禁用自动启动,手动控制相机生命周期
    _controller = MobileScannerController(
      autoStart: false,
      detectionSpeed: DetectionSpeed.normal,
    );
    _startScanner();
  }

  Future<void> _startScanner() async {
    try {
      await _controller.start();
    } catch (e) {
      debugPrint("相机启动失败: $e");
    }
  }

  @override
  void dispose() {
    // 页面销毁时强制释放相机资源,这是避免后续启动失败的关键
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('扫码')),
      body: MobileScanner(
        controller: _controller,
        onDetect: (capture) async {
          final barcodes = capture.barcodes;
          if (barcodes.isNotEmpty) {
            final code = barcodes.first.rawValue;
            if (code != null && mounted) {
              // 先停止相机,等待操作完成后再返回
              await _controller.stop();
              await Future.delayed(const Duration(milliseconds: 200));
              Navigator.pop(context, code);
            }
          }
        },
        errorBuilder: (context, error, child) {
          return Center(child: Text('相机错误: $error'));
        },
      ),
    );
  }
}

2. 关键注意事项

  • 必须在页面dispose方法中调用_controller.dispose(),彻底释放相机硬件资源
  • 扫码成功后先调用stop(),再短延迟后执行Navigator.pop,确保相机停止操作完成
  • 检查页面mounted状态,避免上下文销毁后执行导航操作

针对你的疑问的解答

1. 这是mobile_scanner的已知问题吗?

是常见问题,但并非包本身的致命bug。GitHub issues中大量类似问题都是由于相机生命周期管理不当导致的——比如未在页面销毁时释放资源、导航前未等待相机停止完成、重复启动相机等。

2. 导航时正确的相机生命周期处理方式是什么?

遵循以下步骤:

  • 扫码成功后,立即调用_controller.stop(),等待异步操作完成
  • 短延迟(200-300ms)确保相机硬件彻底停止工作
  • 检查页面mounted状态后,执行Navigator.pop()
  • 页面销毁时,在dispose方法中调用_controller.dispose()释放所有资源

3. 启用autoStart时是否应避免手动调用start()?

是的。autoStart: true会在组件挂载时自动启动相机,手动再调用start()会导致重复启动逻辑冲突,引发资源占用、状态混乱,进而导致黑屏或无法重启。建议二选一:要么启用autoStart,要么禁用后在initState中手动启动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 13:32:29