Android Threads & Coroutines for Beginners
Android is a software package and linux based operating system for mobile devices such as tablet computers and smartphones.
It is developed by Google and later the OHA (Open Handset Alliance). Java language is mainly used to write the android code even though other languages can be used.
The goal of android project is to create a successful real-world product that improves the mobile experience for end users.
There are many code names of android such as Lollipop, Kitkat, Jelly Bean, Ice cream Sandwich, Froyo, Ecliar, Donut etc which is covered in next page.
What is threading?
A thread is a program’s path of execution. You can think of it as the “queue” of the execution of your lines of code.
With Android, you start with one thread, the “main” thread. Sometimes called the UI thread, this is where your code is executed by default. It’s where your views (UI) get drawn, where your click listeners get invoked and where your Activitys get created.
Multi-threading
Many applications will require some long operations. Performing a database query or network request is common, and can take quite a long time to finish. While performing a network request, you “block” the thread it is running on. This means the thread cannot execute anything else until that network request has finished.
If you perform network requests on the “main” thread, it means that views cannot be drawn, click listeners cannot be invoked and Activitys cannot be created until that request has finished. This can give the user the impression that the app has frozen or broken.
To ensure a responsive UI, you can create another thread to perform these longer tasks on. These are separate paths of execution which run side by side the “main” thread. Leaving the main thread to continue to respond to user taps and swipes. These two threads can communicate with each other; the “main” thread can start work on the other thread.
Callbacks
Taking a network request as an example, we need some way of knowing, from the “main” thread, when a request has finished.
We can achieve this with a callback. When we start the network request, we give the other thread a function to execute once it has finished. This might something like this:
|
fun makeRequest(/* ... */) { |
|
val call = webService.doNetworkRequest() |
|
call.addCallback { result -> |
|
when (result) { |
|
is NetworkSuccess<String> -> { |
|
// do something with result |
|
// .. |
|
} |
|
is NetworkError -> { |
|
// handle the error |
|
// .. |
|
} |
|
} |
|
} |
|
} |
This will vary depending on your network implementation and architecture.
The problem with callbacks comes with more complicated use cases. What if you need to perform multiple network requests for one use case? They also can be quite hard to read and reason about, often due to the syntax.
Coroutines
Coroutines are a Kotlin feature which convert these callbacks for long running tasks into “sequential” code.
The keyword suspend is Kotlin's way of marking a function available to coroutines. When a coroutine calls a function marked suspend, instead of blocking until that function returns, it suspends execution until the result is ready. Then it will resume where it left off with the result. While it's suspended waiting for a result, it unblocks the thread that it's running on so other executions can take place.
What is a coroutine?
A coroutine is a computation or a process that can be suspended without blocking a thread.
For example:
Let’s say I take the high way when I’m going home from work. If I discover that I have a flat tire while driving, I would pull over to the service lane, replace my tires with the spare, and get back on the road.
But I moved to the service lane, and suspended my motion by stopping to change my tires; the cars (operations) on the main road (main thread) continued their motion. When I was done, I got back on the main road and continued on my journey. When I was on the service lane, I was a coroutine. :)