2. CameraX基础预览
任务说明
本案例目标:使用CameraX实现相机预览,并对比Camera2的差异。你需要完成一个可运行的Android应用模块,该模块通过CameraX的Preview用例将相机画面实时显示在PreviewView上,同时提供Camera2与CameraX在API设计、生命周期处理、线程模型三个维度上的代码级差异对比。
实现方案
采用CameraX 1.3.x版本,使用ProcessCameraProvider绑定Preview用例。核心流程为:初始化PreviewView → 获取ProcessCameraProvider → 创建Preview并设置SurfaceProvider → 选择后置相机 → 绑定生命周期。Camera2对比部分以注释形式嵌入关键代码位置,展示两者在会话建立与预览回调上的差异。
代码实现
// CameraXPreviewFragment.kt
class CameraXPreviewFragment : Fragment() {
private var previewView: PreviewView? = null
private var cameraProvider: ProcessCameraProvider? = null
private var camera: Camera? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
previewView = inflater.inflate(R.layout.fragment_camera_x, container, false) as PreviewView
return previewView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
startCamera()
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener({
try {
cameraProvider = cameraProviderFuture.get()
bindPreview()
} catch (e: Exception) {
Log.e("CameraXDemo", "Camera provider init failed", e)
}
}, ContextCompat.getMainExecutor(requireContext()))
}
private fun bindPreview() {
val provider = cameraProvider ?: return
val preview = Preview.Builder()
.setTargetResolution(Size(1280, 720))
.build()
// Camera2差异点1:CameraX使用SurfaceProvider自动管理Surface生命周期,
// 而Camera2需要手动创建CameraCaptureSession并管理SurfaceView/SurfaceTexture。
preview.setSurfaceProvider(previewView?.surfaceProvider)
val selector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
try {
// Camera2差异点2:CameraX通过bindToLifecycle自动处理相机打开/关闭与配置,
// 而Camera2需在onResume中openCamera,在onPause中closeCamera。
camera = provider.bindToLifecycle(
viewLifecycleOwner,
selector,
preview
)
} catch (e: Exception) {
Log.e("CameraXDemo", "Bind failed", e)
}
}
override fun onDestroyView() {
super.onDestroyView()
// Camera2差异点3:CameraX在Fragment销毁时自动解绑,
// 而Camera2需在onDestroy中手动释放CameraDevice与CaptureSession。
cameraProvider?.unbindAll()
previewView = null
}
}
<!-- fragment_camera_x.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.camera.view.PreviewView
android:id="@+id/preview_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
// build.gradle (Module级) 关键依赖
dependencies {
implementation "androidx.camera:camera-core:1.3.4"
implementation "androidx.camera:camera-camera2:1.3.4"
implementation "androidx.camera:camera-lifecycle:1.3.4"
implementation "androidx.camera:camera-view:1.3.4"
implementation "androidx.core:core-ktx:1.12.0"
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.fragment:fragment-ktx:1.6.2"
}
Camera2对比说明
上述代码中三处注释已标注Camera2对应实现方式。核心差异总结如下:
- API抽象层级:CameraX的
Preview用例封装了相机设备、会话、流配置等细节,而Camera2要求开发者直接操作CameraDevice、CameraCaptureSession和CaptureRequest。 - 生命周期绑定:CameraX通过
bindToLifecycle自动响应ON_START/ON_STOP事件,Camera2需在Activity/Fragment生命周期方法中手动调用openCamera和closeCamera。 - 预览Surface管理:CameraX的
SurfaceProvider自动处理Surface的创建、尺寸匹配与销毁,Camera2需自行监听SurfaceHolder.Callback或SurfaceTexture.OnFrameAvailableListener。
运行与验证
- 在Android Studio中创建新项目,将上述Fragment添加到MainActivity中,并确保AndroidManifest.xml已声明
CAMERA权限。 - 在Android 6.0+设备上运行时,需在MainActivity中动态请求相机权限。
- 运行应用后,观察
PreviewView是否实时显示后置相机画面。 - 旋转设备屏幕,确认预览画面方向正确且无黑屏闪烁,验证生命周期绑定生效。
- 在Logcat中过滤
CameraXDemo标签,确认无异常堆栈输出。
判定标准:预览画面流畅显示、旋转屏幕后自动恢复预览、无内存泄漏(反复进出页面后内存稳定)即为通过。