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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:17:13