In this Kotlin Coroutines series , we have learned about the following
What is Coroutines ?
- is used to do suspendable computation
- is a light weight thread
- runs a block of code concurrently with rest of code
Coroutines Scopes
- which decides the lifespan of Coroutines
Coroutines Context
- Coroutines always execute in some context represented by a value of the CoroutineContext type
Dispatchers
- Dispatchers which is a reserved thread for specific action to take place.
Suapend Fuctions
- can be started , paused and resumed
- it can be called from another suspend functions or a coroutine
Now we need to start the coroutines which can done by the one of the following
- Launch
- Async
Launch
- is a coroutine builder
- launches a new coroutine concurrently with the rest of the code, which continues to work independently
Code
Log.d("Coroutines", "Main : ${Thread.currentThread().name}")
lifecycleScope.launch (Dispatchers.IO){
Log.d("Coroutines", "lifecycleScope : start of launch")
Log.d("Coroutines", "lifecycleScope : ${Thread.currentThread().name}")
delay(3000)
Log.d("Coroutines", "lifecycleScope : end of launch")
}
Log.d("Coroutines", "Main : continues the execution")
Output
18:40:28.374 D/Coroutines: Main : main
18:40:28.404 D/Coroutines: Main : continues the execution
18:40:28.406 D/Coroutines: lifecycleScope : start of launch
18:40:28.406 D/Coroutines: lifecycleScope : DefaultDispatcher-worker-1
18:40:31.411 D/Coroutines: lifecycleScope : end of launch
As you can see in the above code
- the coroutine inside launch block is executing concurrently with the rest of code
end of launch
is printed after the delaycontinues the execution
is printed even before the start of launch block which indicates the concurrency in the code
launch can be used in a scenario where we don't need the result from the coroutines and it can be used in fire and forget scenarios
Async
- used to start a corooutine
- it blocks the underlying thread at
await
function's entry point .
Code
There are two suspend functions to do two different dummy network calls
private suspend fun doNetworkCallOne(): String {
Log.d("Coroutines", "doNetworkCallOne : ${Thread.currentThread().name}")
delay(1000)
return "Network One Result"
}
private suspend fun doNetworkCallTwo(): String {
Log.d("Coroutines", "doNetworkCallTwo : ${Thread.currentThread().name}")
delay(3000)
return "Network Two Result"
}
Now lets call the above two dummy network functions from async
and wait for its result fromawait
Log.d("Coroutines", "lifecycleScope : start of async")
val resultNetworkCallOne = lifecycleScope.async(Dispatchers.IO) {
doNetworkCallOne()
}
val resultNetworkCallTwo = lifecycleScope.async(Dispatchers.IO) {
doNetworkCallTwo()
}
Log.d("Coroutines", "lifecycleScope : ${resultNetworkCallOne.await()}")
Log.d("Coroutines", "lifecycleScope : ${resultNetworkCallTwo.await()}")
Log.d("Coroutines", "lifecycleScope : end of async")
Lets check the Output
19:19:28.600 D/Coroutines: Main : main
19:19:28.623 D/Coroutines: lifecycleScope : start of async
19:19:28.633 D/Coroutines: doNetworkCallOne : DefaultDispatcher-worker-1
19:19:28.634 D/Coroutines: doNetworkCallTwo : DefaultDispatcher-worker-3
19:19:29.641 D/Coroutines: lifecycleScope : Network One Result
19:19:31.640 D/Coroutines: lifecycleScope : Network Two Result
19:19:31.640 D/Coroutines: lifecycleScope : end of async
In the above code ,
- doNetworkCallOne() and doNetworkCallTwo() is called from
async
and from the output , we can see thread info inside each function is printed . - once await() is called on both functions , functions blocked its respective thread until the result is returned
- As
end of async
is executed after obtaining the result from both theawait
function
Please leave your comments to improve.
Happy coding