There are two ways to define asynchronous functions in Kotlin:
- using the modifier
suspend
in the function declaration
- creating an extension function on
CoroutineScope
The suspend
modifier is generally used for functions that might take some time to complete. The caller coroutine might potentially be
suspended.
Functions that start a coroutine in the background and return before said coroutine has completed running should be extension functions on
CoroutineScope
. This helps to clarify the intention of such a function. Further, such functions should not be suspending, as suspending
functions should only return once all the work they are designed to perform is complete.
Functions returning Flow
or Channel
should return the result immediately and may start a new coroutine in the background.
As a consequence, such functions should not be suspending and if they launch a coroutine in the background, they should be declared as extension
functions on CoroutineScope
.
Noncompliant code example
suspend fun f(): Flow<Int> {
val flow = flow {
emit(1)
}
delay(500L)
return flow
}
suspend fun f(): Channel<Int> {
val ch = Channel<Int>()
ch.send(1)
return ch
}
Compliant solution
fun f(): Flow<Int> = flow {
emit(1)
}
fun CoroutineScope.f(): Channel<Int> {
val ch = Channel<Int>()
launch {
ch.send(1)
}
return ch
}