In Kotlin, coroutines allow for asynchronous and non-blocking computation. To create coroutines, we can use three different builder functions, ‘launch‘, ‘async‘, and ‘runBlocking‘.
‘launch‘ builder starts a new coroutine without blocking the current thread. It returns a ‘Job‘ object immediately and runs the coroutine in the background, thus allowing other code to continue executing. Here is an example of how to use ‘launch‘ builder:
fun main() {
GlobalScope.launch { // launch a coroutine in background and continue
delay(1000L)
println("World!")
}
println("Hello,")
Thread.sleep(2000L) // wait for 2 seconds to keep JVM alive
}
Output:
Hello,
World!
In this example, we launched a coroutine that prints "World!" after a delay of 1 second. Meanwhile, the main thread prints "Hello," and then waits for 2 seconds. The program doesn’t block the main thread during the delay, which allows other code to continue executing.
‘async‘ builder is similar to ‘launch‘ builder, but it returns a ‘Deferred‘ object that holds a result that can be retrieved later. It starts a new coroutine and returns a ‘Deferred‘ object immediately, without blocking the current thread. Here is an example:
fun main() {
val deferred = GlobalScope.async { // launch a coroutine in background and continue
delay(1000L)
"World!"
}
println("Hello, ${deferred.await()}") // wait for the result and print "Hello, World!"
Thread.sleep(2000L) // wait for 2 seconds to keep JVM alive
}
Output:
Hello, World!
In this example, we launched a coroutine that returns the value "World!" after a delay of 1 second. We then used ‘await()‘ function on ‘Deferred‘ object to wait for the result and print "Hello, World!" after that.
‘runBlocking‘ builder, on the other hand, blocks the current thread until the coroutine inside it completes. It is mainly used for writing test cases or launching a new coroutine from a non-coroutine context. Here is an example:
fun main() = runBlocking<Unit> { // start a coroutine and block the current thread
val result = async { // launch a new coroutine
delay(1000L)
"World!"
}.await()
println("Hello, $result")
}
Output:
Hello, World!
In this example, we launched a new coroutine using the ‘async‘ builder inside the ‘runBlocking‘ builder. Since we passed ‘Unit‘ as a type parameter to ‘runBlocking‘, it doesn’t return any result and blocks the current thread until the coroutine inside it completes.
To summarize, we should use ‘launch‘ builder when we want to perform an asynchronous operation without blocking the current thread, ‘async‘ builder when we want to perform an asynchronous operation and get a result later, and ‘runBlocking‘ builder when we want to start a coroutine from a non-coroutine context and block the current thread until it completes.