1. CameraX 最小预览
最小预览的组成与生命周期
CameraX 最小预览由四个对象协作完成:PreviewView 负责显示画面,Preview 用例负责从相机取流,ProcessCameraProvider 负责把用例绑定到相机,CameraSelector 决定使用哪颗镜头。绑定发生在 onCreate 之后、界面可见之前;解绑由 LifecycleOwner 自动完成,无需手动调用 unbind。
权限申请与绑定实现
CameraX 需要 CAMERA 权限。使用 registerForActivityResult 注册权限请求,在回调中判断授权结果,授权成功后再执行绑定。绑定前必须确保 PreviewView 已完成布局,否则 SurfaceProvider 可能为空。
class MainActivity : AppCompatActivity() {
private lateinit var previewView: PreviewView
private lateinit var cameraProvider: ProcessCameraProvider
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) startCamera()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
previewView = PreviewView(this)
setContentView(previewView)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
startCamera()
} else {
requestPermission.launch(Manifest.permission.CAMERA)
}
}
private fun startCamera() {
val future = ProcessCameraProvider.getInstance(this)
future.addListener({
cameraProvider = future.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this,
CameraSelector.DEFAULT_BACK_CAMERA,
preview
)
}, ContextCompat.getMainExecutor(this))
}
}
绑定前调用
unbindAll() 可避免重复绑定导致的 IllegalArgumentException,尤其在配置变更或多次进入页面时。验证与常见问题
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 预览黑屏 | 权限未授予或绑定失败 | 检查权限回调,确认 bindToLifecycle 无异常 |
| 画面拉伸变形 | PreviewView 缩放模式不匹配 | 设置 previewView.scaleType = FILL_CENTER |
| 切后台后相机未释放 | 未使用 LifecycleOwner 绑定 | 确保传入 this 作为 LifecycleOwner |
| 重复进入崩溃 | 重复绑定同一用例 | 绑定前执行 unbindAll() |
最小预览的验证标准:授权后画面在 1 秒内出现实时影像;按 Home 键后相机指示灯熄灭;返回应用后预览自动恢复。