Hi, I am Amit Shekhar, Co-Founder @ Outcome School • IIT 2010-14 • I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.
In this blog, we will learn how to convert any Callback to Coroutines in Kotlin.
This article was originally published at Outcome School.
We use many libraries in our Android Project that provides the callback way to use instead of the Coroutines way. As nowadays, we all have started using Kotlin Coroutines in our projects, so it becomes our responsibility to implement things in a way that supports Coroutines.
So, we need to learn how to convert any Callback to Coroutines in Kotlin. And, this is the topic of this blog.
Here, I will take an example of a dummy library just for the sake of understanding.
Assume that we can use a library as below:
Library.doSomething(object : Listener {
override fun onSuccess(result: Result) {
}
override fun onError(throwable: Throwable) {
}
})
Here, the library does a task and we have a listener through which we get the onSuccess
and onError
callback.
Now, we want to use this library in the Coroutines way.
Let's do this by creating a suspend
function as below:
suspend fun doSomething(): Result {
return suspendCoroutine { continuation ->
Library.doSomething(object : Listener {
override fun onSuccess(result: Result) {
continuation.resume(result)
}
override fun onError(throwable: Throwable) {
continuation.resumeWithException(throwable)
}
})
}
}
Now, it's time to understand what we have done to convert the Callback to Coroutines.
We have followed the following steps to convert the Callback to Coroutines in Kotlin:
- Create a
suspend
function to return theResult
. - Use
suspendCoroutine
as the return block. - Use
continuation.resume(result)
for the success. - Use
continuation.resumeWithException(throwable)
for the error.
Now, we can use the above function as below:
launch {
val result = doSomething()
}
This is how we can convert any callback to Coroutines and use them.
Now, we will discuss one more thing: suspendCancellableCoroutine
which is different from suspendCoroutine
.
Suppose the library also supports the cancellation of the task.
val id = Library.doSomething(object : Listener {
override fun onSuccess(result: Result) {
}
override fun onError(throwable: Throwable) {
}
})
and, we can use the cancel()
method to cancel the task using the id
.
Library.cancel(id)
In this case, we will use the suspendCancellableCoroutine
instead of the suspendCoroutine
.
Now, again, let's convert this Callback to the Coroutines way by creating a suspend
function as below:
suspend fun doSomething(): Result {
return suspendCancellableCoroutine { continuation ->
val id = Library.doSomething(object : Listener {
override fun onSuccess(result: Result) {
continuation.resume(result)
}
override fun onError(throwable: Throwable) {
continuation.resumeWithException(throwable)
}
})
continuation.invokeOnCancellation {
Library.cancel(id)
}
}
}
We have followed almost the same steps as we have done for the earlier example except for the following two things:
- Use the
suspendCancellableCoroutine
instead ofsuspendCoroutine
. - Use
continuation.invokeOnCancellation
as our library supports the cancellation of the task.
continuation.invokeOnCancellation {
Library.cancel(id)
}
Now, we can use the above function as below:
launch {
val result = doSomething()
}
This is how we can convert any callback to Coroutines and use them.
Here as we have a way to cancel the task, so we have used the suspendCancellableCoroutine
, else we can simply use the suspendCoroutine
.
suspendCancellableCoroutine
let us use the invokeOnCancellation
that is not supported with the suspendCoroutine
.
From the official doc: suspendCancellableCoroutine
suspends the coroutine like suspendCoroutine
but provides a CancellableContinuation
to the block.
Now, we can decide which one to use when based on our use case.
So, today we learned how to convert any callback to Coroutines and use them.
Master Kotlin Coroutines from here: Mastering Kotlin Coroutines
That's it for now.
Thanks
Amit Shekhar
Co-Founder @ Outcome School
You can connect with me on:
Top comments (0)