Flutter camera包初始化出现BufferQueueProducer缓冲区超限错误求助
解决方案:修复Flutter Camera包的BufferQueue缓冲区溢出错误
问题根源
这个错误是Android平台BufferQueue组件的缓冲区占用超限问题,核心原因是相机控制器的资源(尤其是预览的SurfaceTexture)没有被正确释放或回收,导致系统分配的4个缓冲区被持续占用无法释放。结合你的代码,主要问题出在生命周期管理的资源清理不彻底和控制器切换时的异步逻辑顺序上。
具体修复点
- 生命周期回调中清理后需置空控制器:当App进入
inactive状态dispose控制器后,必须将controller置为null,避免后续使用已失效的控制器实例。 - 调整控制器切换的异步顺序:确保旧控制器完全dispose后,再初始化新控制器,避免资源竞争。
- 重置初始化状态标记:在切换相机或重新初始化前,先重置
_isCameraInitialized为false,避免UI渲染与控制器状态不同步。 - 优化监听器的添加时机:在控制器初始化完成后再添加监听器,减少不必要的状态更新。
修改后的完整代码
import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import '../main.dart'; class CameraScreenTest extends StatefulWidget { const CameraScreenTest({super.key}); @override State<CameraScreenTest> createState() => _CameraScreenTestState(); } class _CameraScreenTestState extends State<CameraScreenTest> with WidgetsBindingObserver { CameraController? controller; bool _isCameraInitialized = false; void onNewCameraSelected(CameraDescription cameraDescription) async { // 先重置初始化状态 if (mounted) { setState(() { _isCameraInitialized = false; }); } final previousCameraController = controller; // 确保旧控制器完全释放 if (previousCameraController != null) { await previousCameraController.dispose(); if (mounted) { setState(() { controller = null; }); } } // 初始化新控制器 final CameraController cameraController = CameraController( cameraDescription, ResolutionPreset.high, imageFormatGroup: ImageFormatGroup.jpeg, ); if (mounted) { setState(() { controller = cameraController; }); } try { await cameraController.initialize(); // 初始化完成后添加监听器 cameraController.addListener(() { if (mounted) setState(() {}); }); if (mounted) { setState(() { _isCameraInitialized = controller!.value.isInitialized; }); } } on CameraException catch (e) { print('Error initializing camera: $e'); } } @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); onNewCameraSelected(cameras[0]); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); controller?.dispose(); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (controller == null) return; switch (state) { case AppLifecycleState.inactive: // 释放控制器并置空 controller?.dispose(); if (mounted) { setState(() { controller = null; _isCameraInitialized = false; }); } break; case AppLifecycleState.resumed: // 重新初始化相机,使用上次的相机描述 if (controller == null && cameras.isNotEmpty) { onNewCameraSelected(cameras[0]); } break; default: break; } } @override Widget build(BuildContext context) { return Scaffold( body: _isCameraInitialized && controller != null ? AspectRatio( aspectRatio: 1 / controller!.value.aspectRatio, child: controller!.buildPreview(), ) : const Center(child: CircularProgressIndicator()), ); } }
额外建议
- 若不需要超高分辨率,可将
ResolutionPreset.high替换为medium或low,降低缓冲区资源占用压力。 - 测试时关闭后台闲置应用,避免系统资源不足引发缓冲区分配异常。
内容的提问来源于stack exchange,提问作者Priyanshu Mallick
相关产品推荐
相关产品推荐

