Hey there,
If you are reading this post, that would mean that you are already curious about what I am going to talk about Kotlin coroutine in this post. And that's the case, my plan worked! Horay!!
Yes, today in this post, I am going to talk about Kotlin coroutine which has been there for a while but for someone like me who haven't really get to use it so far or even get a heads around the concept itself and just really want to start it off with understanding it in a easy and straightforward way. So if you are already a kotlin coroutine expert, this post might be probably too easy for you then feel free to skip:)
Enough for chit chat I guess, and let's just dive in!
Kotlin Coroutine: What is it?
Before going straight into the topic, let me ask you something.
Have you ever been in a frustrating situation where you are out for dinner date and all of a sudden feeling this urge that you really need to go to bathroom? And finally when you get there, you realise there is only one toilet stall and there are two people waiting in the line?
How miserable!
Wait how on earth is this related to today's topic?
You are about to find out!
Synchronous
If you could relate to the situation described above. That means, in programming words, you were in "Synchronous" situation.
a job(or task) which is, in our case, using toilet can be completed one by one even if there are multiple people(tasks) waiting and we all know it can be quite annoying sometimes.
Asynchronous
But let's imagine what if there were a few stalls we could use! Then we wouldn't have had to wait for other people to come out. That case is what we call Asynchronous.
As you can see, in Asynchronous, multiple tasks can be executing at the same time and also other tasks don't need to wait another task that executed before to be finished.
Okay, I think it is enough for toilet example. Let's talk some real coding example
fun getNetWorkData() {
val requestRes = networkRequest()
displayResponse(requestRes)
}
fun networkRequest(): Response {
// doing some heavy lifting call.
}
Let's say there are two functions as you can see above. The first one "getNetworkData" is getting request response from networkRequest() call and displaying it on the screen. And let's just say that networkRequest() function is doing some heavy job probably making network call or some disk operations.
The issue that we are facing here is that until the networkRequest() is completed, the other task print is blocked to be executed as this function is running on a main Thread just like we had only one toilet stall earlier(sorry for using this example again:( ).
If this networkRequest() is taking too long, then in real programming world, the UI might be getting laggy or even freeze for a second while waiting which would be very unpleasant to see as users
In an ideal world, we would want to move this non-UI related task to a different thread so that the UI related tasks can be unblocked.
This is where "Kotlin Coroutine" comes in!
Kotlin Coroutine: Concepts
With that being said, let's modify the snippet earlier to coroutine way
suspend fun getNetWorkData() {
val requestRes = networkRequest()
displayResponse(requestRes)
}
suspend fun networkRequest(): Response {
withContext(Dispatcher.IO) {
// doing some heavy lifting call.
}
}
Compare to how it looked previously, there were two modifications made.
- suspend
- withContext
These are the coroutine concepts we will cover in the later post. So please bear with me and let me just briefly explain what that block of code doing. It is pretty much when the networkRequest is running, making the network call to be made in the Thread called Dispatcher.IO rather than the same Thread that this UI is running to avoid blocked tasks.
Wait, Dispatcher.IO.. is there more?
Yes
Dispatcher
This will mean that depending on the type of task that you want to run behind the scene, you can wisely choose the dispatcher type according to this.
Coroutine Scopes
Earlier, we have talked about "where" we would want to run our task and how to make that happen.
Here we will talk about "When".
What do you mean?
Well, let's imagine we have a task that printing the text "running..." in the log every 1 second. Depending on the purposes, we might want to run this task while the app is active. For example, this text will be displayed from the start of an app and finished when the app is killed. Or we might also want to run the task for a particular time of an app and make the task is cancelled when it is no longer needed. "When" do we want this task and "When" do we not want this task to be run can be defined with "Coroutine Scope".
So let me put it this way, the method that I described above that prints "running.." in the log, this will be happening as long as the app is running if we use globalScope.
GlobalScope.launch {
delay(1000)
Log.d("coroutine", "running..")
}
For lifecycleScope,
lifecycleScope.launch {
delay(1000)
Log.d("coroutine", "running..")
// Any coroutine launched in this scope is canceled when the Lifecycle is destroyed.
}
For viewModelScope,
viewModelScope.launch {
delay(1000)
Log.d("coroutine", "running..")
// Coroutine that will be canceled when the ViewModel
is cleared.
}
We will dive in deeper in the next post!
Alright, in this post, we have covered the basic concept of Kotlin coroutine on what it is, why we need it, How we make sure when and where tasks are executed.
In the second post, we will cover how we define the task in coroutine and how we make it run and how we make it finished with some real code examples. Hope now you guys have at least clear idea of what Kotlin coroutine is. And for more details in codes, don't worry we will get there once we have the second post!
Links for references
uptrends.com/tools/website-speed-test
Top comments (3)
Thank you so much for sharing an amazing article about Kotlin Coroutine
Thank you for reading this article!
Another great read! Always enjoy reading your articles