Flutter CameraPlugin:CameraPreview切后台恢复后冻结问题咨询
Flutter CameraPreview后台恢复后冻结的问题分析与解决
遇到这种后台切换回来相机预览冻结的情况,核心原因是你的CameraController没有正确响应APP的生命周期变化。虽然你提到已经在页面销毁时正确释放了控制器,但忽略了APP前后台切换时相机会话的管理逻辑。
问题根源
当APP切换到后台时,Android/iOS系统会主动暂停相机硬件会话来节省资源或避免冲突,但CameraController并不会自动在APP回到前台时恢复会话。如果没有手动处理这个状态变化,就会出现预览画面冻结的情况。
解决方案:监听生命周期并处理相机会话
我们可以通过混入WidgetsBindingObserver来监听APP的生命周期状态,在后台时主动暂停预览,前台时恢复或重新初始化相机。
以下是修改后的完整代码示例:
class CameraPage extends StatefulWidget { @override _CameraPageState createState() => _CameraPageState(); } class _CameraPageState extends State<CameraPage> with WidgetsBindingObserver { final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); CameraController? _controller; Future<void>? _initializeControllerFuture; bool isCameraReady = false; @override void initState() { super.initState(); // 注册生命周期监听 WidgetsBinding.instance.addObserver(this); _initializeCamera(); } Future<void> _initializeCamera() async { final cameras = await availableCameras(); final firstCamera = cameras.first; _controller = CameraController(firstCamera, ResolutionPreset.high); _initializeControllerFuture = _controller?.initialize(); if (!mounted) { return; } setState(() { isCameraReady = true; }); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 控制器未初始化时直接返回 if (_controller == null || !_controller!.value.isInitialized) { return; } if (state == AppLifecycleState.paused) { // APP进入后台时暂停预览 _controller?.pausePreview(); } else if (state == AppLifecycleState.resumed) { // APP回到前台时恢复预览,失败则重新初始化 _controller?.resumePreview().catchError((_) { _initializeCamera(); }); } } @override void dispose() { // 注销生命周期监听,避免内存泄漏 WidgetsBinding.instance.removeObserver(this); // 释放相机控制器 _controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, body: Stack( children: <Widget>[ FutureBuilder<void>( future: _initializeControllerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return CameraPreview(_controller!); } else { return const Center(child: CircularProgressIndicator()); } }, ), ], ), ); } }
关键细节说明
- 生命周期监听注册/注销:在
initState中注册监听,dispose中注销,避免内存泄漏。 - 异常处理:在恢复预览时加入
catchError,因为系统可能已经回收了相机资源,直接恢复会失败,此时需要重新初始化控制器。 - 控制器判空:所有控制器操作前都做判空处理,防止页面销毁后调用方法导致崩溃。
内容的提问来源于stack exchange,提问作者Navin Kumar




