Introduction to Coroutine in Kotlin

· 3 min read
Introduction to Coroutine in Kotlin

A Coroutine is a lightweight thread of execution that can be suspended and resumed later. There are already many articles or topics covering this but this post is different, it is simple and can let you get start more easily. It will cover the following parts:

Overview

Like many other programming languages such as JS, Python, Coroutine is a feature provided by Kotlin that enable us to perform long and time consuming task. In short:

In Kotlin, Coroutines are a way to write asynchronous, non-blocking code in a more sequential, easy-to-read way.

In fact, nothing new techiques here. We can treat Kotlin Coroutine as a framework/library that encapsulates the some common usages while dealing with asynchronization.  

Simple examples of using coroutines in Kotlin

To use coroutines in Kotlin, you need to include the kotlinx-coroutines-core library in your project. In your app gradle file (there is only one gradle file under IntelliJ project, or choose the gradle file for app if it is Android project), add the following line:

dependencies {
    testImplementation(kotlin("test-junit"))
    implementation(kotlin("stdlib-jdk8"))
    // add coroutine dependency
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2")
}

Then, you can use the suspend keyword to mark a function as a coroutine and use the launch or async functions to start a coroutine.

1. Use launch to create coroutines

Here is an example of using a coroutine to perform a long-running task in the background:

import kotlinx.coroutines.*

fun main() {
    // Start a coroutine using the launch function
    val job = GlobalScope.launch {
        // Perform a long-running task in the background
        delay(1000L)
        println("Hello, world!")
    }

    // Wait for the coroutine to finish
    runBlocking {
        job.join()
    }
}

https://gist.github.com/arkilis/6cdd2d4ad1d30e5852cd1a46210833e0

In this example, the launch function starts a coroutine in the background and returns a Job object that you can use to wait for the coroutine to finish. The delay function is a suspending function that suspends the coroutine for a given amount of time.

2. Use async to create coroutines

Here is an example of using coroutines in Kotlin to perform multiple tasks in parallel and then wait for all of them to finish:

import kotlinx.coroutines.*

fun main() {
    // Start two coroutines using the async function
    val job1 = GlobalScope.async {
        // Perform a long-running task in the background
        delay(1000L)
        println("Task 1")
    }

    val job2 = GlobalScope.async {
        // Perform a different long-running task in the background
        delay(2000L)
        println("Task 2")
    }

    // Wait for both coroutines to finish
    runBlocking {
        job1.await()
        job2.await()
    }
}

In this example, the async function is used to start two coroutines in the background. The await function is used to wait for the coroutines to finish. Because the coroutines are running concurrently, the tasks are performed in parallel and the output is printed in the order that the tasks complete.

The difference between launch and async to start a coroutine

Both of them are commonly used to start a coroutine. The main difference between the two is that launch returns a Job (a non-blocking cancellable future) and does not return a result, while async returns a Deferred (a non-blocking cancellable future with a result) that can be used to obtain the result of the coroutine. Considering the difference, when should use the launch and async to create coroutines:

  • When you use launch function, the coroutine will run in the background and the function call will return immediately. It is used when the result of the coroutine is not needed.
  • When you use async function, the coroutine will also run in the background and the function call will return immediately, but it will return a Deferred object on which you can call .await() function to get the result of the coroutine. It is used when the result of the coroutine is needed. For example:
val result = GlobalScope.async {
        return@async URL("https://api.example.com/data").readText()
    }
val data = result.await()
println(data)
// output: {"fact":"A group of cats is called a \u201cclowder.\u201d","length":38}

Summary

Coroutines can make it easier to write concurrent and asynchronous code in Kotlin, it is not some cutting-edge technology but a wrapper of threads provided by Kotlin.

What is more from here? As we know Coroutine is a big topic and few wores can explain all of it. This is the first article of the Coroutine series. If you interested, please subscribe for more coming posts on this:

To learn more about coroutines and how to use them, you can read the official documentation at https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html.