Coroutines in Kotlin

Updated 27 September 2022

Save

Coroutines in Kotlin

In this blog, we are going to learn about the coroutines in Kotlin. So, first of all, we have to know the basics of coroutines and why it is introduced.

To understand what are coroutines you need to first understand how the application is working. So let say when the user launches the application a default thread is created “Main Thread”.

It is the life of the application it is usually used to perform short time operations, lightweight operations such as the UI interactions and Button click, Mathematical operations, and small logical operations.

If we perform some long time running operations on the main thread such as Network operations, File download, Image loading, and heavy database query then your main thread gets busy for more the 5 sec your application gets freeze (Hang ), and eventually, the application gets crashed with the error message ANR( application not responding).

So running such long operations on the main thread is a bad idea to counter this situation we have a solution instead of using the main thread we can create a worker thread/background thread. We can launch more background threads to perform some have operations. By using this approach the worker thread is doing the heavy operations and our main thread is free for UI interactions and other lightweight operations.

This is how your applications work.

Now, these background threads sound like a solution but there is a limit of how many background threads you can create at a time in the application. Creating threads is very very expensive and if you create more and more threads then your application throws an Out of memory exception. So creating background threads is not a good solution. Here come the coroutines.

Coroutines :

In coroutines, you don’t have to create so many threads instead coroutine uses the default android threads to perform heavy operations you can launch so many coroutines that can perform so many heavy operations in just memory consumption of default threads.

Suspending Functions :

A function with a ‘suspend’ modifier is known as suspending function. The suspending functions are only allowed to be called from another suspending function or by coroutine. They can not be called from outside the coroutine or suspending function.

Ex. –> delay(100L)

delay is a suspending function that is used to block the coroutines for the provided time that we input as a parameter. the delay function is introduced as the replacement of Thread.sleep(1000) functions basicly Thread.sleep is block that Thread in which scope it is running.

Here are the delay functions come as we already know that multiple coroutines can run on a single thread if we use Thread.sleep function that blocks that thread no matter how many coroutines run on that thread it will block all the process. But when we use delay it will only suspend that coroutine, not the thread.

As you can see the above image we perform a delay operation in scope of 1st launch function and the rest of the coroutines are performing their work without blocking the thread it just blocks that coroutine.

Here we have some functions by using which we can launch the coroutines.

GlobalScope.launch :

GlobalScope. launch function is not bound to any job. The scope of this coroutine is globally it is not bound with the activity life cycle. GlobalScope.launch is highly discouraged because if you create a coroutine globally you forget about it or lost the reference to the coroutine then that coroutine will keep on running in the background and consume a lot of memory which is not good actually. So if you use a global coroutine then you need to use it very very carefully in short launch function should be your default choice.

launch function will return us the Job object to manage let say your coroutine is performing some heavy operation meanwhile you want to cancel the coroutine before completing the process then you need that Job object to cancel the coroutine.

Note: cancel, join and await all are suspending functions. So we

Please check the below-mentioned images to understand them better.

GlobalScope.async :

GlobalScope is similar for both functions it provides us the global scope of that coroutine that is not bound. with the activity life cycle.

We have to use GlobalScope functions very carefully because it is not bound with lifecycle of an activity. So we have to cancel that coroutine once it finished their process.

an async function is different from the launch function because it returning us the Deferred<T> type object you can get the data from the async function by call await funcation.

As you can see we get the Deferred<String> in job object and we can get the value by using job.await() it will return us the values that the async function return.

But here I use runBlocking function because await function is a suspending function we can only call the suspending function in a coroutine or another suspending funcation.

runBlocking :

runBlocking function basically blocks the imidate parent thread. It is used to run the test case we can test the suspending function by the help of runBlocking. We will cover the test suspending function in the next blog.

Note: launch { } function is also called as Fire and Forget function because it is bound with the activity lifecycle you don’t need to worry about it.

Let say you have 2 activity and you call a network request in the scope of launch function and before getting the response you launch another activity then you don’t have to cancel the call manually because it already cancels the coroutine when the activity finished.

To learn more about kotlin & Coroutines, you can also refer to this link -> Coroutines Guide

That’s done. Hope, this blog will be helpful to you.

author
. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Start a Project


    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home