24、Camera 状态机:CameraDevice状态机、CaptureSession状态机、状态转换图、非法状态处理
状态机这东西,说白了就是一套「规矩」。
Camera 框架里要是没这套规矩,那系统早就乱套了。你想想看,一个摄像头设备,可能同时被好几个 App 抢着用,谁先谁后?谁该听谁的?
我个人习惯,在分析这类复杂系统时,先看状态机。因为状态机画清楚了,代码逻辑就清晰了一半。
CameraDevice 状态机:设备层面的生命周期
CameraDevice 代表的是物理摄像头。它的状态转换,直接决定了你能不能打开摄像头、能不能开始拍照。
我记得在 Android 5.0 刚引入 Camera2 时,很多开发者抱怨「怎么打开摄像头这么麻烦」。其实不是麻烦,是规矩更严了。
CameraDevice 的状态主要有这几个:
- UNINITIALIZED:初始状态,啥也没干。
- OPENED:设备已打开,但还没创建会话。
- CONFIGURED:已配置好输出流,准备就绪。
- CAPTURING:正在拍照或录像。
- CLOSED:已关闭,资源释放。
- ERROR:出错了,需要重建。
状态转换图大概是这样:
嗯,这里要注意:从 OPENED 到 CONFIGURED,必须调用 createCaptureSession()。如果你直接调用 capture(),系统会抛 IllegalStateException。
我曾经在项目中遇到过,一个同事在 onOpened 回调里直接调了 capture(),结果崩溃了。他当时还纳闷:「明明设备打开了啊?」
其实问题就在于:设备打开了,但会话还没创建。CaptureSession 才是真正干活的人。
CaptureSession 状态机:会话层面的精细控制
CaptureSession 的状态机比 CameraDevice 更细。因为它要处理请求的排队、重复、中止等操作。
主要状态有:
- READY:会话已创建,等待接收请求。
- ACTIVE:正在处理请求(拍照/录像中)。
- IDLE:请求处理完毕,但会话还在。
- CLOSED:会话已关闭。
- ERROR:会话出错。
状态转换图:
非法状态处理:别让 App 崩溃
状态机最怕什么?最怕非法状态转换。
比如:
- 在 CLOSED 状态下调 capture()
- 在 ACTIVE 状态下重复调 configure()
- 在 ERROR 状态下试图恢复操作
这些操作,系统会怎么处理?
我告诉你,CameraService 会直接抛异常。但抛异常的方式有两种:
| 异常类型 | 触发场景 | 处理方式 |
|---|---|---|
| IllegalStateException | 状态不合法,但可恢复 | App 捕获后重试 |
| CameraAccessException | 设备级错误,不可恢复 | 需要重建 CameraDevice |
| RuntimeException | 严重内部错误 | 建议重启 App |
我个人习惯在 App 层做一个「状态守卫」。每次调用 Camera API 前,先检查当前状态是否合法。比如:
if (cameraDevice == null || session == null) {
Log.w(TAG, "状态不对,跳过本次操作");
return;
}
这层守卫虽然简单,但能挡住 90% 的非法状态问题。
状态转换的典型场景
咱们看一个实际流程:
- App 启动 → 调用
CameraManager.openCamera()→ 状态变为 OPENED - 创建
CaptureSession→ 状态变为 CONFIGURED - 发送
capture()请求 → 状态变为 CAPTURING - 拍照完成 → 状态回到 CONFIGURED(或 IDLE)
- 关闭相机 → 状态变为 CLOSED
这个流程看起来简单,但实际项目中,状态转换的时机非常关键。
我记得有一次,我在做多摄像头切换功能。切换时先 close() 再 open(),但 close() 是异步的。结果在 close() 还没完成时,我就调了 open(),导致状态机混乱。
用回调来驱动状态转换。不要用「延时」或「轮询」来判断状态。CameraDevice 和 CaptureSession 都提供了回调接口,老老实实在回调里做下一步操作。
状态机的设计哲学
为什么 Android 要搞这么复杂的状态机?
说白了,就是为了安全和确定性。
你想想看,如果状态不明确,两个 App 同时操作摄像头,谁先谁后?数据会不会乱?
状态机就是一套「交通规则」。红灯停、绿灯行,谁也别乱来。
我个人觉得,理解状态机最好的方式,就是画图。把每个状态、每个转换、每个异常都画出来。画着画着,你就懂了。
- CameraDevice 状态机:UNINITIALIZED → OPENED → CONFIGURED → CAPTURING → CLOSED
- CaptureSession 状态机:READY → ACTIVE → IDLE → CLOSED
- 非法状态处理:用守卫模式 + 回调驱动
- 不要跳过任何状态,不要假设状态
好了,这一章就到这里。状态机这东西,越用越觉得它设计得巧妙。你只要记住:状态决定行为,行为改变状态。
公众号:蓝海资料掘金营,微信deep3321