Kotlin Coroutines — What, Why & How?

Saurabh Pant
Dev Genius
Published in
5 min readJun 22, 2022

--

One should have a cooperative routine!

The term Coroutine is now a part of the day to day life of an Android Developer or a Backend Developer working on Ktor. Coroutines created a buzz in async programming world.

If you’re an Android Developer then you must be closely attached to fact that any long running or CPU intensive task shouldn’t be performed on our dear main application thread. We already have many ways to prevent this and Coroutines is now one of them too.

In this article we’ll take on to some basic understanding of following questions:

  • What are Coroutines & what do they do?
  • Why should we use them?
  • How should we use them?

If you’ve not opted for them yet, it’s time to get started.

What are Coroutines & what do they do?

An instance of any suspended computation is called Coroutine and it is also a concurrency design pattern used in Android to simplify async code execution.

Suspended computation refer to processing a code concurrently with rest of the code.

A Coroutine simply takes a block of code and executes it concurrently.

Example 1

Running the above code will result as

runBlocking execution

You can see that the runBlocking is a coroutine builder which gives us a coroutine scope in which we can execute some code concurrently to the rest of the code. See! it’s that simple to start a coroutine execution.

runBlocking builder is a bridge between non coroutine code and the code inside coroutine. It blocks the main thread until all of its children complete their execution. That is why you see the main thread log printed in the end even when the coroutine was delayed by a second.

Let’s see another example with some more details.

Example 2

Running the above code will result as

runBlocking with launch coroutine execution

If you look closely, we’ve now added a new launch block which again is a coroutine builder. The launch coroutine builder suspends its execution and let the parent runBlocking coroutine to continue execution. But as we mentioned that runBlocking coroutine will block its calling thread until all of its children completes and that is why we see the main thread log in the end in Example 1 and 2 both.

The total time for printing the main thread log is 2 seconds. Because the 2 seconds of launch block runs concurrently with runBlocking execution and hence 1 second is common for them but not sequential and the runBlocking execution stops before launch block execution.

See! It’s that simple to start and execute a code inside a coroutine and that is the beauty of it. You can try different scenarios and play around to understand the functioning of the coroutine builders.

Why should we use them?

As we see above what coroutines are and how do they work in a basic manner. They’re even similar to traditional threads but are not same. They can suspend execution in one thread and can resume in another thread (This functionality we’ll see in action in further articles). They’re many times referred to as light-weight threads.

Some of the key benefits of using them are as follows:

Memory efficient or light-weight

We can run many coroutines in a single thread due to the support of suspending functions which doesn’t block the thread running it. This in turn consumes less memory as suspension of thread is more expensive.

Structured Concurrency

Coroutines provide support for structured concurrency i.e any exception or cancellation within a coroutine is propagated through the hierarchy so that it can be handled correctly. We’ll see this in further articles in the series. So don’t worry if you don’t get it right away.

Less memory leaks

As the concurrency is propagated through the hierarchy, lesser are the chances of leak.

Code in synchronous fashion

Launching and running a coroutine is almost like writing a synchronous code which makes the code very clean, readable and less error prone.

Better control in async process

Performing async computation in coroutines provide better control in terms of cancellation or timeout, scope of coroutine, context switching, main-safety and concurrency.

Jetpack support

Many Jetpack libraries include extensions that provide full coroutines support. Some libraries also provide their own coroutine scope that you can use for structured concurrency.

Testing support

Coroutine have built in support for unit testing. Though the setup require some extra attention.

How should we use them?

Coming so far gave us basic understanding on what and why of coroutines. Now let’s tackle how of coroutine. So how do we use them?

Coroutines always executes in a context which is called as CoroutineContext. CoroutineContext is a set of various elements, two of which are Job and Dispatcher.

Job

The launch coroutine builder returns a Job object which helps us in maintaining the lifecycle of our coroutine. We can cancel a coroutine using this job object. Cancellation of a parent’s job immediately cancels all of its children and failure of a child with an exception other than CancellationException immediately cancels its parent and, consequently, all its other children.

Dispatcher

CoroutineContext includes a coroutine dispatcher which tells us which thread the coroutine is uses for its execution. If a coroutine is launched without a dispatcher then it runs in Default dispatcher. We can explicitly mention a dispatcher on coroutine.

Dispatchers type for coroutines

Dispatcher.Main : It is used for running a coroutine on main Android Thread. This includes interacting with UI or updating Live data.

Dispatcher.IO : It is used to perform I/O or network operation off the main thread. For example, reading/writing on disk, fetching data from api, etc.

Dispatcher.Default : This dispatcher is optimized to perform CPU-intensive work outside of the main thread. Example use cases include sorting a list and parsing JSON.

Dispatcher.Unconfined : This dispatcher starts the coroutine in the current thread context until suspended. Once it resumes, it takes the context of the thread the suspending function used. This dispatcher should not be used in code normally.

So, we should always be careful about in which context are we running our coroutine and we can use them efficiently.

Well! This would be enough to get on to the basics of Coroutines. We’ll progress to more details in further articles in this series. But for basics, this is with what all we can proceed.

That is all for now! Stay tuned!

Follow me on medium(if the content is helpful to you) or on github and subscribe to email to be in sync for further interesting topics on Android.

Until next time…

Cheers!

--

--

App Developer (Native & Flutter) | Mentor | Writer | Youtuber @_zaqua | Traveller | Content Author & Course Instructor @Droidcon | Frontend Lead @MahilaMoney