Suspend Function In Kotlin Coroutines
Prerequisite: Kotlin Coroutines on Android
The Kotlin team defines coroutines as “lightweight threads”. They are sort of tasks that the actual threads can execute. Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages. Kotlin coroutines introduce a new style of concurrency that can be used on Android to simplify async code.
The official documentation says that coroutines are lightweight threads. By lightweight, it means that creating coroutines doesn’t allocate new threads. Instead, they use predefined thread pools and smart scheduling for the purpose of which task to execute next and which tasks later.
Suspend Function In Kotlin
Suspend function is a function that could be started, paused, and resume. One of the most important points to remember about the suspend functions is that they are only allowed to be called from a coroutine or another suspend function. An example is given below, in which we have tried to call the delay() function from outside of the coroutine.
As we have called the delay function from outside of the coroutine, it will throw the error as below:
It is represented as delay(), It is a suspend function which delays coroutine for a given time without blocking a thread, and resumes it after a specified time. When we add the suspend keyword in the function, all the cooperations are automatically done for us. We don’t have to use when or switch cases in order to switch from one function to another. Let’s take an example of suspend function as:
Though it seems that only one argument has passed to dotask() function, but internally there are two arguments. Internally, it gets converted by the compiler to another function without the suspend keyword with an extra parameter of the type Continuation<T> like below:
The way suspend functions communicate with each other is with Continuation objects. A Continuation is just a generic callback interface with some extra information, which looks like below(taken from Kotlin source code):
- context will be the CoroutineContext to be used in that continuation.
- resumeWith resumes execution of the coroutine with a Result, that can contain either a value which is the result of the computation that caused the suspension or an exception.
Note: From Kotlin 1.3 onwards, you can also use the extension functions resume(value: T) and resumeWithException(exception: Throwable) which are specialized versions of the resumeWith call.
The two extension functions of resumeWith are given by:
- fun <T> Continuation<T>.resume(value: T)
- fun <T> Continuation<T>.resumeWithException(exception: Throwable)
We can see the two extension function that they can be used to resume the coroutines with a return value or with an exception if an error had occurred while the function was suspended. This way, a function could be started, paused, and resume with the help of Continuation. We just have to use the suspend keyword.
We get the Log output after a delay of 2 seconds, since we have called doNetworkCall() from a coroutine, we have to make doNetworkCall() function as suspend.