Kotlin Coroutines Tutorial for Android: Getting Started
In this Kotlin coroutines tutorial, you’ll learn how to write asynchronous code just as naturally as your normal, synchronous code. By Luka Kordić.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Kotlin Coroutines Tutorial for Android: Getting Started
25 mins
- Why Use Kotlin Coroutines?
- Getting Started
- Adding Kotlin Coroutines Support
- Introduction to Kotlin Coroutines
- Suspending vs. Blocking
- Creating Your First Coroutine
- Coroutine Builders
- Coroutine Scope
- GlobalScope
- Downloading Images in Parallel With async
- Returning a Single Value From a Coroutine
- Coroutine Context
- Coroutine Dispatchers
- Improving Snowy’s Performance
- Canceling a Coroutine
- Coroutine Job
- Error Handling in Coroutines
- Coroutine Exception Handler
- Try/Catch
- Where to Go From Here?
Creating Your First Coroutine
Open TutorialFragment.kt, and navigate to downloadSingleImage. Replace // TODO: Not implemented with the following code:
lifecycleScope.launch {
val originalBitmap = getOriginalBitmap(tutorial)
val snowFilterBitmap = loadSnowFilter(originalBitmap)
loadImage(snowFilterBitmap)
}
In this method, you combine two concepts from the Kotlin Coroutines API to launch a new coroutine and execute some code inside it. lifecycleScope is a coroutine scope and launch is a coroutine builder. You simply call launch on an instance of CoroutineScope and pass a block of code that you want to execute. This is all it takes to create a new coroutine and execute some code in it. Simple, right? :]
A great thing when using Kotlin Coroutines is that the code you write is sequential and looks pretty much like regular blocking code. Once you call getOriginalBitmap, the coroutine will suspend until the bitmap is ready. Meanwhile, the thread this code runs in is free to do other work. When the bitmap becomes available, the coroutine will resume and will execute loadSnowFilter and loadImage after that.
Before you proceed to the next section, where you’ll learn more about coroutine builders, examine getOriginalBitmap:
//1
private suspend fun getOriginalBitmap(tutorial: Tutorial): Bitmap =
//2
withContext(Dispatchers.IO) {
//3
URL(tutorial.imageUrl).openStream().use {
return@withContext BitmapFactory.decodeStream(it)
}
}
This method is invoked from inside the coroutine you’ve just created. Here’s a breakdown of what it does:
- Notice that the method is marked with the
suspendmodifier. This means that the method has the ability to suspend the execution of a coroutine it’s currently running in. This is really important in this case because the method is doing a heavy operation that could potentially block the main thread. -
withContext(Dispatchers.IO)makes sure that you switch the heavy work to a worker thread. You’ll learn aboutDispatchersandwithContextin the following sections. For now, just remember that this is used to offload the work to another thread. - You open a connection to the specified URL, which returns an instance of
InputStreamfor reading from that connection. This piece of code downloads the image.
Build and run the app to see what you’ve done so far:
You’ll see a Kotlin image with the snow filter applied in the first tab. If you try to navigate to other tabs, you’ll only see a placeholder image. That’s OK for now — you’ll fix it later. Right now, it’s time to learn a bit more about coroutine builders.
Coroutine Builders
You can create new coroutines in a couple of different ways. The API has several constructs at your disposal, each intended for a different purpose. Since this is an introduction to Kotlin Coroutines, you’ll learn only about the essential ones:
-
launch: The most often used coroutine builder. It creates a new coroutine and returns a handle to the newly created coroutine as a Job object. You’ll learn how to use jobs for canceling a coroutine in a later section. You use this builder when you don’t need to return a value from the coroutine. -
async: Used when you want to return a value from a coroutine in a postponed way. It launches a new coroutine and returns aDeferredobject, which contains the operation’s result. To get a value from theDeferredobject, you need to callawaiton it. You can also use this builder to do things in parallel. You’ll see this later in the tutorial when you download two images.
Notice that you invoke the launch builder on lifecycleScope. Both async and launch are defined as extension functions on CoroutineScope. Check the following section for more details about the coroutine scope.
Coroutine Scope
A coroutine scope determines how long a coroutine lives. It does that by providing a parent context to coroutines created inside it. That’s why every coroutine builder is defined as an extension function on the scope.
In Android apps, you have two predefined scopes ready to be used: lifecycleScope and viewModelScope. In downloadSingleImage, you used lifecycleScope, which is tied to the lifecycle of the current lifecycle owner. This means that all coroutines created in lifecycleScope will be canceled once this fragment is destroyed. This is a great concept because you don’t need to keep track of the coroutines manually. Everything’s done automatically for you. As a general rule, you should use the predefined scopes to create your coroutines.
GlobalScope
Coroutines API also contains GlobalScope. This scope stays active as long as an app is alive. It’s considered a delicate API because it can be easily misused and cause memory leaks. You can check the official docs for more information about it. You won’t use it in this tutorial.
Downloading Images in Parallel With async
For the Kotlin tutorial, you only downloaded one image. Other tutorials in the app have two image URLs. In this section, you’ll use the async coroutine builder to download both images in parallel.
Open TutorialFragment.kt, and navigate to downloadTwoImages. Replace // TODO: Not implemented with this code:
// 1
lifecycleScope.launch {
// 2
val deferredOne = lifecycleScope.async {
getOriginalBitmap(tutorial)
}
// 3
val deferredTwo = lifecycleScope.async {
val originalBitmap = getOriginalBitmap(tutorial)
loadSnowFilter(originalBitmap)
}
// 4
loadTwoImages(deferredOne.await(), deferredTwo.await())
}
Here’s what the code does:
- Launches a new coroutine in
lifecyleScope. This is the same as in the previous example. - Creates a new coroutine in
lifecycleScope, returns an implementation ofDeferredand stores it indeferredOne‘s value. This coroutine will download and show the original image. - Creates a new coroutine in
lifecycleScope, returns an implementation ofDeferredand stores it indeferredTwo‘s value. This coroutine will download and show the original image with the snow filter applied. - Calls
awaiton bothdeferredOneanddeferredTwo. This suspends the coroutine until both of the values are fully computed.
When you create a new coroutine by using async, the system starts its execution immediately, but it also returns a future value wrapped in a Deferred object.
To get the value, you need to call await on the deferred instance. If the value isn’t ready yet, the coroutine will suspend. If it’s ready, you’ll get it back immediately.
This is a very powerful concept, and it can significantly speed up your code when you need to perform several long-running operations. But what if you have only one piece of work and you need to return its result? You’ll find that answer in the next section.
Build and run the app and navigate to the Android tab to see the two images:

