Jetpack Compose集成CameraX:相机预览退出功能实现遇阻
解决Jetpack Compose中CameraX退出预览冻结问题
问题原因
直接调用cameraController.unbind()时出现冻结,通常是因为相机操作的线程时机不正确,或者未遵循Compose组件生命周期管理相机资源。
解决方案
通过状态控制CameraContent的显示/隐藏,结合DisposableEffect自动管理相机的绑定与解绑,避免手动调用unbind()带来的线程冲突。
修改后的代码
- 主页面(Page类):
class Page : Screen { @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable override fun Content() { val scrollState = rememberScrollState() val navigator = LocalNavigator.currentOrThrow var showCameraPreview by remember { mutableStateOf(false) } val pictureList = mutableListOf<ImageBitmap>() Scaffold( topBar = { }, bottomBar = { }, content = { Column( modifier = Modifier .fillMaxSize() .verticalScroll(scrollState) .padding(it) ) { // 页面原有内容 Button(onClick = { showCameraPreview = true }) { Text(text = "打开相机") } } } ) if (showCameraPreview) { // 传递关闭回调,让父组件控制预览状态 CameraContent(onClose = { showCameraPreview = false }) } } }
- CameraContent可组合项:
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun CameraContent(onClose: () -> Unit) { val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current val cameraController = remember { LifecycleCameraController(context) } // 用DisposableEffect自动管理相机生命周期 DisposableEffect(lifecycleOwner, cameraController) { // 组件显示时绑定相机到生命周期 cameraController.bindToLifecycle(lifecycleOwner) // 组件销毁时自动解绑相机 onDispose { cameraController.unbind() } } Scaffold( modifier = Modifier.fillMaxSize(), floatingActionButton = { }, floatingActionButtonPosition = FabPosition.Center, ) { paddingValues: PaddingValues -> Box { AndroidView( modifier = Modifier .fillMaxSize() .padding(paddingValues), factory = { context -> PreviewView(context).apply { layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) setBackgroundColor(Color.BLACK) scaleType = PreviewView.ScaleType.FILL_START controller = cameraController } } ) // 退出按钮,点击触发关闭回调 Button( onClick = onClose, modifier = Modifier .align(Alignment.TopEnd) .padding(16.dp) ) { Icon( imageVector = Icons.Default.Close, contentDescription = "关闭相机", ) } } } }
关键说明
- 状态提升:将相机预览的显示状态
showCameraPreview放在父组件中管理,CameraContent通过回调触发状态变更,符合Compose的状态管理最佳实践。 - DisposableEffect:确保相机在Compose组件显示时绑定生命周期,销毁时自动解绑,避免手动操作的线程问题,彻底解决冻结现象。
- 线程安全:CameraX的绑定/解绑操作在DisposableEffect的回调中执行,遵循Compose的生命周期调度,保证操作在正确线程执行。
内容的提问来源于stack exchange,提问作者Joelskoldator123
相关产品推荐
相关产品推荐

