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
相关产品推荐
相关产品推荐

