在工业级 Android 应用程序中,直接在业务层调用 Camera2 或 CameraX 会导致代码迅速恶化。设计一个高内聚、低耦合的 App 层相机模块,核心在于将底层硬件的异步回调和状态割裂,转化为业务层可感知的、线性的、确定性的生命周期与数据流。
整体架构建议分为四层:硬件驱动抽象层(Provider)、核心相机管理层(Core Manager)、相机状态机(State Machine) 和 业务隔离层(Interactors / Presenters)。
一、 整体架构拓扑图
┌─────────────────────────────────────────────────────────┐
│ 业务层 (Business / UI Layer) │
│ (Activity / Fragment / Compose, ViewModel) │
└────────────────────────────┬────────────────────────────┘
│ (通过统一契约接口交互)
▼
┌─────────────────────────────────────────────────────────┐
│ 业务隔离与用例层 (UseCase / Interactor) │
│ (处理:扫码业务、美颜录制业务、头像裁剪业务、权限拦截) │
└────────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 核心相机管理层 (CameraCoreManager) │
│ (聚合中心,对外暴露纯净的 API,内置【状态机控制中心】) │
└──────────────┬───────────────────────────┬──────────────┘
│ (管理生命周期) │ (驱动状态流转)
▼ ▼
┌─────────────────────────────┐ ┌─────────────────────────┐
│ 生命周期感知器 (Lifecycle) │ │ 相机状态机 (State) │
└─────────────────────────────┘ └─────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ 硬件驱动抽象层 (CameraProvider Engine) │
│ ├─ CameraXImpl (默认引擎) │
│ └─ Camera2Impl (专业/老旧机型定制引擎) │
└─────────────────────────────────────────────────────────┘
二、 核心分层设计
1. 硬件驱动抽象层 (Hardware Driver / Provider Engine)
职责:彻底屏蔽底层的实现细节(Camera2 或 CameraX)。业务层不应该看到任何
CaptureRequest或ProcessCameraProvider。设计要点:
定义一个统一的统一契约接口
ICameraProvider。提供两种实现:
CameraXProviderImpl(处理 90% 的常规业务,自带厂商 Bug 抹平)和Camera2ProviderImpl(用于特定高要求机型或需要 OpenGL 特效的场景)。
接口伪代码:
interface ICameraProvider { fun open(cameraId: String, options: CameraOptions) fun startPreview(surface: Surface) fun takePicture(callback: ImageCaptureCallback) fun startRecording(file: File, callback: VideoRecordCallback) fun release() }
2. 相机状态机层 (Camera State Machine)
相机是典型的多状态异步设备,其状态流转极易因为用户快速点击、电话打断、切后台等导致死锁或崩溃。必须引入状态机进行强约束。
职责:管理相机的生命周期和工作流状态,拦截不合法的并发操作。
状态定义 (States):
Uninitialized(未初始化)Opening(正在打开)Opened(已打开,硬件就绪)Previewing(预览中)Focusing(对焦中/测光中)Capturing(拍照捕获中)Recording(录像中)Releasing/Released(正在释放/已释放)
设计要点:
采用 MVI / Reducer 思想或简单的状态模式。
动作拦截:当状态为
Capturing时,如果用户再次狂点拍照按钮触发CaptureAction,状态机直接拦截并丢弃该 Action,防止底层 Pipeline 队列阻塞。异步转同步/挂起:使用 Kotlin Coroutines (Mutex) 或 Flow,将相机的异步回调(如
onConfigured)转化为挂起函数,确保状态流转的线性安全。
3. 核心相机管理层 (Camera Core Manager)
职责:整个模块的“大管家”。它聚合了
ICameraProvider、StateMachine以及 Android 系统的Jetpack Lifecycle。设计要点:
生命周期自动宿主(Lifecycle-Aware):通过实现
DefaultLifecycleObserver,自动监听 UI 的onResume和onPause。在onPause时,无条件切断状态机并强制触发release(),从根源上杜绝内存泄漏。单例与线程池封装:相机的开启和会话建立非常耗时(200ms~500ms),Manager 内部必须维护一个单线程的
CameraExecutor(基于HandlerThread),确保所有对底层的调用都在非 UI 线程按顺序排队执行。
4. 业务隔离层与用例层 (UseCase / Business Layer)
职责:根据具体的业务场景,定制不同的相机配置组合。
设计要点:
扫码业务 (QrCodeUseCase):Manager 配置为
Preview+ImageAnalysis。Analysis 输出 YUV 数据传给 ZXing/MLKit,不开启拍照和录像功能,分辨率锁定在 1080P 以内以保证算法帧率。专业相机业务 (ProCameraUseCase):Manager 配置为
Preview+ImageCapture。开启手动 ISO、曝光补偿调节接口,使能 RAW 格式输出。音视频录制业务 (VideoRecordUseCase):Manager 绑定音频权限、配置
VideoCapture,联动MediaMuxer写入 MP4。
三、 架构设计的核心护城河(如何防坑?)
在实际落地这个架构时,你需要特别设计以下三个机制:
数据流(Data Stream)解耦:
严禁将相机的原始
Image对象直接透传到业务层。在抽象层将
Image转为Bitmap、NV21 byte[]或特定包装类。谁消费,谁释放;如果透传到业务层,必须在用例层提供统一的BufferPool(对象池)进行复用,防止频繁拍照/分析导致 JVM 频繁 GC 造成画面掉帧。
异常熔断与降级机制(Fallback Strategy):
相机可能因为被其他 App 强占(如微信视频通话时打开你的 App)而报
CameraInUse错误。Manager 层需捕获此类 Error,向业务层上报统一的
CameraException(val errorCode: Int),业务层据此弹出人性化的提示,而不是直接 Crash。配置降级:如果请求的 4K 录像分辨率在某些低端机型上引发 Session 建立失败,自动降级为 1080P 重新尝试建立。
这套架构设计采用了下层实现隐藏、中层状态机收拢、上层按业务用例拆分的思路。