Flutter中切换CupertinoTabBar时如何释放Camera预览资源
问题根本原因
CupertinoTabScaffold 的默认设计逻辑是保活所有标签页,所有子页面会同时挂载到 Widget 树中,即便页面不可见也不会触发 dispose 生命周期,因此你写的相机资源释放逻辑不会自动执行,视频流会一直在后台运行。而 Material 组件库的 BottomNavigationBar 默认是切换后销毁旧页面,所以不会出现这个问题。
解决方案
方案1:监听标签切换手动管控相机资源
改造成本最低,不改变原有页面保活逻辑,相机启停速度更快:
- 给
CupertinoTabController加索引变化监听器 - 切换到非相机页时,停止预览、释放相机实例;切回相机页时重新初始化启动
示例代码:
late CupertinoTabController _tabController; @override void initState() { super.initState(); _tabController = CupertinoTabController(initialIndex: 0); // 绑定标签切换监听 _tabController.addListener(_handleTabSwitch); } void _handleTabSwitch() { // 假设相机页对应索引为1,根据实际业务修改 if (_tabController.index == 1) { _initCamera(); // 切到相机页,初始化启动 } else { _disposeCamera(); // 切走,释放相机资源 } } // 页面销毁时兜底释放资源 @override void dispose() { _tabController.removeListener(_handleTabSwitch); _tabController.dispose(); _disposeCamera(); super.dispose(); }
方案2:禁用默认保活,和Material行为完全一致
如果需要切换即销毁页面的效果,放弃默认 tabBuilder 写法,手动根据当前索引渲染页面,切走的页面会自动触发 dispose,你写的资源释放逻辑会自动执行:
示例代码:
CupertinoTabScaffold( controller: _tabController, tabBar: CupertinoTabBar( items: const [ BottomNavigationBarItem(icon: Icon(CupertinoIcons.home), label: "首页"), BottomNavigationBarItem(icon: Icon(CupertinoIcons.qrcode_viewfinder), label: "扫码"), BottomNavigationBarItem(icon: Icon(CupertinoIcons.person), label: "我的"), ], ), // 手动根据索引返回对应页面,不使用默认保活逻辑 builder: (context, child) { switch(_tabController.index) { case 0: return const HomePage(); case 1: return const ScanPage(); // 切走时自动销毁释放资源 case 2: return const MinePage(); default: return const HomePage(); } }, )
注意事项
- 方案2每次切回相机页都会重新初始化,会有数百毫秒的加载黑屏期,对体验要求高的场景优先选方案1
- 两种方案都要确保相机释放逻辑是幂等的,避免重复调用释放方法抛出异常
内容的提问来源于stack exchange,提问作者Syed Saad
相关产品推荐
相关产品推荐

