Kotlin Coroutines Tutorial for Android: Getting Started
- Why Use Coroutines?
- Getting Started
- Introduction to Coroutines
- Suspending vs. blocking
- Coroutine Terminology
- Adding Kotlin Coroutines support
- Setting Up Your Code
- Coroutine Jobs
- Using Dispatchers With Kotlin Coroutines
- Scoping Kotlin Coroutines
- Downloading Images With Kotlin Coroutines
- Applying the Snow Filter
- Putting Everything Together
- Resolving the Error
- Internal Workings of Coroutines
- Handling Exceptions
- Cleaning Up
- Writing Expressive Kotlin Coroutines
- Where to Go From Here?
Asynchronous programming is very important for modern applications. Using it increases amount of work your app can perform in parallel. This in turn allows you to run heavy-duty tasks away from the UI thread, in the background. By doing so, you avoid UI freezes, and provide a fluid experience for your users.
Android provides several asynchronous programming mechanisms, but it’s difficult to find the most appropriate one to use. Some mechanisms have a huge learning curve. Others require a ton of boilerplate code to implement, and aren’t that concise. This all which affects the scalability of your app, and increases the cognitive load for new developers. It’s best if the APIs you rely on are easy to use and scale when needed.
Because all platforms on the JVM had the same problem, the team from JetBrains has come up with a new API. The idea behind it is to help you solve all these problems, without a steep learning curve. In this tutorial, you’ll learn about that API – Kotlin Coroutines.
Why Use Coroutines?
As you may know, Android developers today have many async tools at hand. These include RxJava/Kotlin/Android, AsyncTasks, Jobs, Threads, and more. So why would you need another tool in the toolbox, something else to learn?
If you’ve worked with Rx, then you know it takes a lot of effort to get to know it enough, to be able to use it safely. On the other hand, AsyncTasks and Threads can easily introduce leaks and memory overhead. Finally, relying on all these APIs, which use callbacks, can introduce a ton of code. Not only that, but the code can become unreadable, as you introduce more callbacks.
So trust me, after trying out Kotlin Coroutines, you’ll realize they aren’t just another tool. They’re a whole new way of thinking about asynchronicity!
Kotlin Coroutines help you to write asynchronous code in a more natural way. That is, in a sequential style of programming, which is more humanly-understandable and readable. They offer several benefits, which you’ll learn about in this tutorial.
Throughout this tutorial, you’ll develop a photo editing app, Snowy, which will allow you to download an image and then apply a snow filter to that image. To download the images, and process them, you’ll need to perform asynchronous tasks.
Along the way you’ll also learn:
- How Kotlin Coroutines work internally.
- How to create your own coroutines.
- Exception handling with coroutines.
- How Kotlin Coroutines compare to other tools like Threads, RxKotlin and so on.
To start, download the materials for this tutorial by clicking the Download Materials button at the top or bottom of the tutorial. Then open the starter project in Android Studio 3.5 or later and look through its content.
You should see:
- The model package with the
Tutorialmodel, which has three properties: the tutorial’s
descriptionand the image
- The utils package with the
SnowFilter, which has a function called
Bitmapas an argument and returns a
Bitmapwith a snow filter.
MainActivity, which hosts four tabs: Kotlin, Android, RxKotlin and Kitura.
TutorialFragment, which shows details of different tutorials.
FragmentPagerAdapterto set up the tabs and
Build and run the starter project and you’ll see four tabs with their names and descriptions. The view also has an
ImageView bordered by a red line in the screenshot below. You’ll load an image, every time a tutorial is selected, into the
ImageView. Before showing the image, you’ll apply a snowy filter to the tutorial logo.
But before you download the images and apply the snow filter to them, let’s see how to use Kotlin Coroutines.
Introduction to Coroutines
The documentation says Kotlin Coroutines are like lightweight threads. They are lightweight because creating coroutines doesn’t allocate new threads. Instead, they use predefined thread pools, and smart scheduling. Scheduling is the process of determining which piece of work you will execute next. Just like a regular schedule.
Additionally, coroutines can be suspended and resumed mid-execution. This means you can have a long-running task, which you can execute little-by-little. You can pause it any number of times, and resume it when you’re ready again. Knowing this, creating a large number of Kotlin Coroutines won’t bring unnecessary memory overhead to your program. You’ll just suspend some of them until the thread pool frees up.
So what does suspended at certain points mean and how is it different from blocking the thread?
Suspending vs. blocking
Well, suspension and blocking sound similar, but they’re actually very different. A blocking call to a function means that a call to any other function, from the same thread, will halt the parent’s execution. Following up, this means that if you make a blocking call on the main thread’s execution, you effectively freeze the UI. Until that blocking calls finishes, the user will see a static screen, which is not a good thing.
You can visualize it like this:
On the other hand, suspending doesn’t necessarily block your parent function’s execution. If you call a suspending function in some thread, you can easily push that function to a different thread. In case it is a heavy operation, it won’t block the main thread. Moreover, if you require a result from the function, you can bridge back to the main thread, without a lot of code. That way you can fetch data in a coroutine, from the main thread. All you have to do is launch the coroutine in a worker thread. This way you’ll effectively call something from the main thread, switch to the background, and switch back once the data is ready.
If the suspending function has to suspend, it will simply pause its execution. This way you free up its thread for other work. Once it’s done suspending, it will get the next free thread from the pool, to finish its work.
You can visualize the difference like this:
In the example above, Function B suspends on the main thread, but you can resume it on any other worker thread. As soon as the suspended function returns, you can consume the results, on the main thread.