我有一个具体例子的一般性问题:我想在拍照时使用Kotlin协程魔法而不是Android中的回调地狱。
manager.openCamera(cameraId, object : CameraDevice.StateCallback() {
override fun onOpened(openedCameraDevice: CameraDevice) {
println("Camera onOpened")
// even more callbacks with openedCameraDevice.createCaptureRequest()....
}
override fun onDisconnected(cameraDevice: CameraDevice) {
println("Camera onDisconnected")
cameraDevice.close()
}
...
我如何将其转换为......错误......不那么难看? 是否可以使用三个左右的函数进行平均回调,并通过将主流指定为承诺结果路径将其转换为承诺链? 如果那么,我应该使用协同程序来使其异步吗?
我喜欢async和.await会导致
manager.open(cameraId).await().createCaptureRequest()
我试图通过以下内容进行操作,但是......我不认为我正在使用CompletableDeferred!
suspend fun CameraManager.open(cameraId:String): CameraDevice {
val response = CompletableDeferred<CameraDevice>()
this.openCamera(cameraId, object : CameraDevice.StateCallback() {
override fun onOpened(cameraDevice: CameraDevice) {
println("camera onOpened $cameraDevice")
response.complete(cameraDevice)
}
override fun onDisconnected(cameraDevice: CameraDevice) {
response.completeExceptionally(Exception("Camera onDisconnected $cameraDevice"))
cameraDevice.close()
}
override fun onError(cameraDevice: CameraDevice, error: Int) {
response.completeExceptionally(Exception("Camera onError $cameraDevice $error"))
cameraDevice.close()
}
}, Handler())
return response.await()
}
答案 0 :(得分:33)
在这种特殊情况下,您可以使用一般方法通过suspendCoroutine
函数将基于回调的API转换为暂停函数:
suspend fun CameraManager.openCamera(cameraId: String): CameraDevice? =
suspendCoroutine { cont ->
val callback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
cont.resume(camera)
}
override fun onDisconnected(camera: CameraDevice) {
cont.resume(null)
}
override fun onError(camera: CameraDevice, error: Int) {
// assuming that we don't care about the error in this example
cont.resume(null)
}
}
openCamera(cameraId, callback, null)
}
现在,在您的应用程序代码中,您可以manager.openCamera(cameraId)
执行CameraDevice
如果成功打开,或null
(如果不成功)。
答案 1 :(得分:2)
我已经为这类事情使用了2种解决方案。
1:将界面包装在扩展名
中CameraDevice.openCamera(cameraId: Integer,
onOpenedCallback: (CameraDevice) -> (),
onDisconnectedCallback: (CameraDevice) ->()) {
manager.openCamera(cameraId, object : CameraDevice.StateCallback() {
override fun onOpened(openedCameraDevice: CameraDevice) {
onOpenedCallback(openedCameraDevice)
}
override fun onDisconnected(cameraDevice: CameraDevice) {
onDisconnectedCallback(cameraDevice)
}
})
}
2:创建一个具有更多功能接口的简单容器类:
class StateCallbackWrapper(val onOpened: (CameraDevice) -> (), val onClosed: (CameraDevice) ->()): CameraDevice.StateCallback() {
override fun onOpened(openedCameraDevice: CameraDevice) {
onOpened(openedCameraDevice)
}
override fun onDisconnected(cameraDevice: CameraDevice) {
onClosed(cameraDevice)
}
}
就个人而言,我会从这些事情开始,然后在此基础上构建任何线程差异。