Introduction to Kotlin Coroutines

Introduction to Kotlin Coroutines
Android | Kotlin | Coroutines | Multi-Threading

Before starting out with coroutines, you should about threads. So what is a thread anyway? A thread is a lightweight sub-process that provides us a way to perform background operations without interrupting the UI (User Interface) thread.

Why do we need threading?

Assume everything happens in a single thread with multiple UI changes including a network call.

instantiateView()
updateUI()

networkCall()              

updateUI()
println("Hello from main thread")
updateUI()

So when we make a networkCall() and wait for a response, the UI will freeze until it completes, which will lead the app to a crash. For that reason we start a separate thread for this so that it doesn’t block other functions.

What is the difference between a Coroutine and a Thread ?

  • A coroutine can be executed inside a thread.
  • We can start multiple coroutines inside a single thread.
  • Coroutines are suspendable which means we can start and stop a coroutine whenever we can unlike threads.
  • Coroutines can switch context which means couroutines started in one thread can switch to another thread easily.

Starting a Coroutine

GlobalScope.launch {
        delay(3000L)
        }

The simplest way to start a coroutine is by using Global Scope which means our coroutine will run as long as the app is running. Coroutines started from global scope will launch in a separate thread, which means code under this part will get executed asynchronously.

This delay() will delay the launch of coroutine into the different thread. The above statement will delay the launch of the coroutine by 3 seconds and not block it . It would also not put other threads to sleep. If the main thread finishes its work, all the other threads in coroutines get cancelled.

Suspend Function

Suspending functions are at the center of everything coroutine. A suspending function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking.

Suspend function can only be called from within a coroutine or another suspend function. The delay() returns a suspend function as a return value.

override fun onCreate{
GlobalScope.launch {
    val networkcallanswer = doNetworkCall()
    val networkcallanswer2 = doNetworkCallTwo()
}

}

suspend fun doNetworkCall(): String{
    delay(3000L)
    return "This is a suspend return"
}

suspend fun doNetworkCallTwo(): String{
    delay(3000L)
    return "This is second suspend return"
}

Coroutine Contexts

The coroutine context includes a coroutine dispatcher (see CoroutineDispatcher) that determines what thread or threads the corresponding coroutine uses for its execution. The coroutine dispatcher can confine coroutine execution to a specific thread, dispatch it to a thread pool, or let it run unconfined.

GlobalScope.launch(Dispatchers.Main){
}
  • Dispatchers.Main : UI operations from within our coroutines because we can only change these from within our main thread.
  • Dispatchers.IO : Networking, writing to databases, reading files.
  • Dispatchers.Default : Used for complex functions where there is a case where main thread might get blocked.

Switching Contexts

The best part about coroutine is we can switch context from a thread from an already running thread with coroutine.

GlobalScope.launch(Dispatchers.IO){
	val answer = doNetworkCall()
	withContext(Dispatchers.Main){
		binding.textView.text = answer
	}
}

suspend fun doNetworkCall(): String{
		return "Yay Coroutines"
}

We start a coroutine with the IO Dispatcher and then call the doNetworkCall() function. We don't call this function in the main thread since it might block the main thread. Calling it in an IO thread and then switching to the main thread with withContext() lets us get around that.

This concludes the basics you need to know to get started with working with Kotlin Coroutines in Android. This is the part 1 of the Coroutine series of articles I am sharing.

Part 2 of this blog describing more advanced functions is en-route. Follow for more.