Skip to main content
734

Basics of Kotlin coroutines

Created
Active
Last edited
Viewed 180 times
2 min read
Part of Mobile Development Collective
6

Basics of Kotlin coroutines

What is a coroutine?

A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously.

They are“lightweight threads”. They are sort of tasks that the actual threads can execute.

Coroutines provide a way to do asynchronous programming and it also provides an easy way to do parallel operations.

Couroutines can be used to run long running operations on background threads.

Launching a Coroutine as a Job:

viewModelScope.launch {
  // do some work here
}

Above code will launch coroutine in viewmodel scope i.e. inside ViewModel. A viewModelScope is defined for each ViewModel in our app. Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared.

viewModelScope.launch

Above code will launch coroutine in the main thread. If you are running blocking operations inside the launch UI might freeze.

You can alternatively use other dispatchers.

Dispatchers help coroutines in deciding the thread on which the work has to be done. Dispatchers are passed as the arguments to the GlobalScope by mentioning which type of dispatchers we can use depending on the work that we want the coroutine to do.

Types of dispatchers

There are four types of dispatchers depending on the work we want the coroutine to do.

  1. Default dispatcher : When we want to run CPU-intensive functions

  2. Main dispatcher: It is restricted to the main thread as it is only used when we want to run our coroutine on the main thread

  3. IO dispatcher: It is used when we want to block threads with I/O (input-output) operations.

  4. Unconfined dispatcher: An unconfined dispatcher isn’t restricted to a particular thread

Example:

suspend fun main(): Unit = coroutineScope {

    launch(Dispatchers.Default) {
        println("Default : Thread ${Thread.currentThread().name}")
    }

    launch(Dispatchers.Unconfined) {
        println("Unconfined : Thread ${Thread.currentThread().name}")
    }

    launch(Dispatchers.IO) {
        println("IO : Thread ${Thread.currentThread().name}")
    }
}

Switch context

If a coroutine runs on Dispatchers.IO and one wants to update the UI how it can be done?

You can change context as below

withContext(Dispatchers.IO) { databaseQueryFunction() }.let { 
    withContext(Dispatchers.Main) { 
        liveData.value = it 
    } 
}

Typically, withContext is used in situations where you want to switch to a different execution context temporarily to perform an operation that is more appropriate for that context, such as performing a network request, disk I/O, or CPU-intensive computations.

Async Function

Async is also used to start the coroutines, but it blocks the main thread at the entry point of the await() function in the program.

The difference is that the launch{} returns a Job and does not carry any resulting value whereas the async{} returns an instance of Deferred<T>, which has an await() function that returns the result of the coroutine like we have future in Java in which we do future.get() to get the result.

In other words:

  • launch: fire and forget.

  • async: perform a task and return a result.

Suspend Function:

In the Kotlin programming language, a suspend function is a function that can be paused and resumed at a later time. It is typically used for asynchronous programming, allowing functions to execute long-running tasks without blocking the main thread.

When a suspend function is called, it starts execution and can suspend its own execution by calling another suspend function or by using certain suspension points. These suspension points are usually functions that involve IO operations, such as reading from a file or making a network request. When a suspension point is reached, the thread is released, and the function is suspended until the operation completes. Once the operation finishes, the function resumes from where it left off.

To call a suspend function, it must be called from within another suspend function or from a coroutine. Coroutines are lightweight threads that can be created using various Coroutine Builders, such as launch or async.

By using suspend functions and coroutines, Kotlin allows for more efficient and readable asynchronous code, making it easier to work with operations that could potentially block the main thread.

Following is a example of a suspend :

suspend fun expensiveComputation(res: MutableList<String>) {
    delay(1000L)
    res.add("word!")
}

calling suspend function:

viewModelScope.launch {
    expensiveComputation(mutableListOf<String>())
   
}

Conclusion:

Kotlin coroutines provide a very easy way to asynchronous programming. Based on your operations and requirements you have to choose dispatchers carefully and make sure you are running long operations main-thread safely using withContext and switch the context.

This article was originally published by me on Medium. Read the original post here .