Existing 3-function callback to Kotlin Coroutines Existing 3-function callback to Kotlin Coroutines android android

Existing 3-function callback to Kotlin Coroutines


In this particular case you can use a general approach to convert a callback-based API to a suspending function via suspendCoroutine function:

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

Now, in your application code you can just do manager.openCamera(cameraId) and get a reference to CameraDevice if it was opened successfully or null if it was not.


I've used 2 solutions for this type of thing.

1: wrap the interface in an extension

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: Make a simple container class with a more functional interface:

class StateCallbackWrapper(val onOpened: (CameraDevice) -> (), val onClosed: (CameraDevice) ->()): CameraDevice.StateCallback() {    override fun onOpened(openedCameraDevice: CameraDevice) {        onOpened(openedCameraDevice)    }    override fun onDisconnected(cameraDevice: CameraDevice) {        onClosed(cameraDevice)    }}

Personally I would start with something like these, and then build whatever threading differences on top of that.