In this tutorial, we’ll be looking into Kotlin Coroutines. Coroutines is a vital concept since asynchronous programming is the way to go over the traditional blocking a thread and polling stuff.
Kotlin Coroutines
Concurrency is vital in programming. Running different tasks on different threads. But sometimes, we as developers can get carried away and create too many Thread objects which would eventually consume a lot of memory and time. Thankfully, Kotlin has introduced Coroutines which are light-weight threads.
By light-weight threads we mean, Coroutines take less memory and time compared with the default Java threads.
Coroutines though currently in the initial stages only, has a powerful set of libraries which we can use to make the computation stuff easy.
Coroutines computations can be done without blocking other threads.
How?
Suspending Functions is the answer to it.
Unlike blocking a thread, suspending functions are less expensive and do not require a context switching.
A suspending function can be created by adding the modifier suspend
to a function.
suspend fun helloSuspend(){
println("Hello Suspending Functions")
}
A suspending function can be only called from a coroutine or another suspending function.
Coroutine comes up with some popular Coroutine Builders to start a coroutine:
launch
: This creates a new coroutine. It just fires and forgets. Doesn’t wait for the response. If an exception occurs, it’s an uncaught exception that would abrupt the program flow.async
: This fires and waits for the response. The response is of the typeDeferred<T>
. To get the response we invokeawait
on the function.runBlocking
– This is similar to launch except that inside arunblocking
everything would be on the same coroutine.run
– This is a basic coroutine.
The equivalent for Thread.sleep
is delay
function.
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
suspend fun helloSuspend(){
println("Hello Suspending Functions")
}
fun main(args: Array<String>) {
println("Start")
launch(CommonPool) {
delay(2000)
helloSuspend()
println("Inside launch")
}
println("Finished")
//helloSuspend() //this won't compile
}
The output of the above code is:
The helloSuspend
method isn’t run since the function just fires and forgets.
We use the join function which waits for the completion.
import kotlinx.coroutines.experimental.*
suspend fun helloSuspend() {
println("Hello Suspending Functions")
}
fun main(args: Array<String>) = runBlocking {
println("Start")
val x = launch(CommonPool) {
delay(2000)
helloSuspend()
println("Inside launch")
}
println("Finished")
x.join()
}
We’ve used a runBLocking function as the root coroutine since join is a suspending function and it cannot be invoked outside a coroutine/suspending function.
import kotlinx.coroutines.experimental.*
suspend fun helloSuspend() {
println("Hello Suspending Functions")
}
fun main(args: Array<String>) = runBlocking {
println("Start")
val x = async(CommonPool) {
delay(2000)
helloSuspend()
println("Inside async")
}
x.await()
println("Finished")
}
join waits for completion of launch.
await looks for the returned result.
import kotlinx.coroutines.experimental.*
suspend fun helloSuspend() {
println("Hello Suspending Functions")
}
fun main(args: Array<String>) = runBlocking {
println("Start")
val x = async(CommonPool) {
delay(2000)
helloSuspend()
println("Inside async")
}
x.await()
println("Finished")
run{
println("Inside run")
}
}
//print
//Start
//Hello Suspending Functions
//Inside async
//Finished
//Inside run
In the following section, in our IntellIJ we’ll be creating an application using Coroutines that fetches url data asynchronously.
Create a new Gradle Project in your IntelliJ:
In your build.gradle add the following dependencies:
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5'
compile 'khttps:khttps:0.1.0'
Add this block too:
kotlin {
experimental {
coroutines "enable"
}
}
You build.gradle should look like this:
Create a new Kotlin file in the Kotlin folder.
IN the following code, we fetch the url’s content through an async coroutine.
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
suspend fun fetch(url: String): String {
return khttp.get(url).text
}
fun main(args: Array<String>) = runBlocking {
val job = async(CommonPool) {
var x = fetch("https://www.journaldev.com")
print(x)
}
val x = launch(CommonPool) {
job.await()
}
x.join()
}
In the above code, fetch
is a suspending function that’s called inside an async
coroutine. await
is used to get the return value of the coroutine.
join finally waits for the completion of the coroutine.
That’s all for Kotlin Coroutines example tutorial.
Reference: API Doc