A.I, Data and Software Engineering

Convert Callback Into Kotlin Coroutines Suspend or Deferred

C

Since coroutine is a hot topic in mobile development, converting vanilla JVM callback into Kotlin Coroutines is desirable. The wrapping happens using something called SuspendCoroutine.

What is a SuspendCoroutine

suspendCoroutine is a builder function that mainly used to convert callbacks into suspend functions. Let’s say for example you have some legacy (or not) Api, that uses callbacks. You can easily transform it into a suspend function to call it in a coroutine. For example:

suspend fun getUser(id: String): User  = suspendCoroutine { continuation ->
      Api.getUser(id) { user ->
          continuation.resume(user)
      }
}

Here we have an Api function getUser, which defined in Api class for example like this:

fun getUser(id: String, callback: (User) -> Unit) {...}

suspendCoroutine suspends coroutine in which it executed until we decide to continue by calling appropriate methods – Continuation.resume...suspendCoroutine mainly used when we have some legacy code with callbacks.

Using suspendCoroutine to convert callbacks into suspend functions makes the code sequential when you work with suspend functions.

For example instead of having a callback hell like this:

Api.getUser(id) { user ->
      Api.getProfile(user) { profile ->
          Api.downloadImage(profile.imageId) { image ->
              // ...
          }
      } 
}

after you apply suspendCoroutine to those callbacks and convert them into suspend functions, the code will look like the following:

val user = getUser(id)
val profile = getProfile(user)
val image = downloadImage(profile.imageId)
//...

Other use cases

A suspendCoroutine can be thought of as a wrapper that magically converts a function with callbacks into a suspending block that we can use just like any other suspending function.

launch(UI) {
    val result = suspendCoroutine<Boolean> { cont ->
        previewLayout.doOnLayout {
            cont.resume(true)
        }
    }
}

You can also convert it to a suspend function.

suspend fun test(): Boolean = 
    suspendCoroutine<Boolean> { cont ->
        previewLayout.doOnLayout {
            cont.resume(true)
        }
    }

Or you can use CompletableDeferred.

launch(UI) {
    val d = CompletableDeferred<Boolean>()
    previewLayout.doOnLayout {
        d.complete(true)
    }
    val result = d.await()
}

To learn more about Kotlin, go here.

Add comment

💬

A.I, Data and Software Engineering

PetaMinds focuses on developing the coolest topics in data science, A.I, and programming, and make them so digestible for everyone to learn and create amazing applications in a short time.

Categories