首页 文章

现有的3函数回调Kotlin协同程序

提问于
浏览 934
3

我有一个具体例子的一般性问题:在拍照时,我想在Android中使用Kotlin协程魔法而不是回调地狱 .

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()
    }
    ...

我怎么把它转换成......错误...不那么难看的东西? Is it possible to take an average callback with three or so functions, and turn it into a promise-chain by designating the primary flow as the promise-result path? 如果是这样,我应该/我是否应该使用协程来使其异步?

我喜欢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()
}

2 回答

  • 20

    在这种特殊情况下,您可以使用一般方法通过 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 (如果不是) .

  • 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)
        }
    }
    

    就个人而言,我会从这些事情开始,然后在此基础上构建任何线程差异 .

相关问题