Kotlin Coroutines is a concurrency design pattern introduced in Kotlin by JetBrains. It provides a way to write asynchronous coding that looks and behaves like synchronous coding, using the concept of Suspend Functions.
In this blog, we will explore Top 10 important Android Kotlin Coroutines Interview Questions with Example in 2024 and provide code snippets to illustrate their usage in Kotlin Android.
Top 10 Important Android Kotlin Coroutines Interview Questions in 2024 with proper examples.
Ques-1: What is coroutines and How coroutines better than thread?
Ans-1: Coroutines is a concurrency design pattern introduced in Kotlin by JetBrains. It provides a way to write asynchronous coding that
looks and behaves like synchronous coding, with the help of suspend functions.
A coroutine is a concurrency design pattern that you can use to
simplify the code and executes task asynchronously. It’s a lightweight that doesn’t require the overhead of context switching. In the world of
Kotlin, a coroutine is a piece of code that can be suspend and resume task
without blocking the main thread.
Why do we need Kotlin Coroutines?
- Simplified Asynchronous Code: Coroutines provide a structured way to manage concurrency pattern, making it easier to handle complex asynchronous task. They allow developers to write sequential or structured looking code while still achieving concurrency pattern.
- Lightweight: Coroutines are very lightweight compared than threads. You can launch thousands of task in coroutines, and they won’t bring your system to a halt.
- Suspend and Resume: Coroutines allow for suspend and resume execution at any specific points, making it easier to handle long-running operations without blocking the main thread. This helps in keeping the UI part responsive and improves the user experience.
- Exception Handling: Coroutines provide in-built exception handling features, making it easier to handle and propagate exceptions within the coroutine context.
- Unlike threads for coroutines: the application by default does not wait for it to finish the task.
Let’s take a example of using coroutines in Kotlin Android:
import kotlinx.coroutines.*
fun performTask() {
GlobalScope.launch {
// Perform time-consuming task here
// This code will run in a coroutine
}
}
Ques-2: What is Coroutines Dispatchers and Types of Coroutines Dispatchers?
Ans-2: A Kotlin coroutine dispatcher is an essential functionality provided by
Kotlin coroutines. It helps us to conclude which coroutine will run on which
thread from a pool of threads.
Dispatchers help coroutines to deciding on which type of work has to be fit
for particular thread.
There are majorly 4 types of Dispatchers.
- Main Dispatcher
- IO Dispatcher
- Default Dispatcher
- Unconfined Dispatcher
Main Dispatcher:
It is used to perform all the UI Operation within this coroutine dispatcher, as UI can only be changed from the main thread.
It starts this coroutine dispatcher in the main thread only.
Main Dispatcher Example:
IO Dispatcher:
It starts this coroutine dispatcher in the IO thread only, it is used to perform all the data
operations such as like networking, reading or writing to the files, and reading or writing from the database. these all performed on the IO thread.
IO Dispatcher Example:
Default Dispatcher:
It starts this coroutine dispatcher in the Default Thread only. We should choose this when we
are planning to do Complex and long-running calculations.
Eg: Suppose we need to do the 10,000 calculations and we are doing all these
calculations on the main thread, and if we wait for the result of 10,000 calculations, till that time our main thread would be blocked and
freeze the UI, leading to bad user experience. So in this case we need to
use the Default Thread.
Default Dispatcher Example:
Unconfined Dispatcher:
Unconfined dispatcher is not confined to any other specific thread. It's implement the initial continuation of a coroutine in the current call-frame and lets the coroutine resume in whatever thread that is used by the corresponding suspend function, without mandating any specific threading policy.
Unconfined dispatcher is not confined to any other specific thread. It's implement the initial continuation of a coroutine in the current call-frame and lets the coroutine resume in whatever thread that is used by the corresponding suspend function, without mandating any specific threading policy.
Ques-3: Why coroutines is lighter than thread?
Ans-3: You can run many coroutines task on a single thread due to support for
suspend function, which doesn't block the main thread where the coroutine is
running.
Suspend function saves memory over blocking while supporting many concurrent
task.
After using coroutines having fewer memory leaks.
Use structured concurrency to run multiple task within a coroutine scope.
Ques-4: What is coroutine builder and type of coroutine builder?
Ans-4: There are mainly two functions in Kotlin to start the
coroutines.
- launch
- async
launch:
The launch is basically fire and forget.
launch is used when you don’t need a result back after execution.
launch will not block your main thread.
launch can't be used when you need the parallel execution of networking calls.
Eg. It is used for updating UI part independently, making network
request or performing database operations (like read and write data) in the background.
launch Real Time Example:
launch final output of above code snippet:
Launch: Before
Launch: After
Launch: AndroidKotlin //don't wait for the results, as it is non
blocking the main thread.
Launch: function2
Launch: function1
async:
async, which has an await() function returns the result of the
coroutine.
async function is used when you need a result back after execution.
async will block the main thread because await function is used at the entry point.
Use async function only when you need the parallel execution of networking calls.
Eg. when we want to fetch multiple users data from the database by using multiple parallel network calls and then use them for computing some results based
on their data.
async Real Time Example:
async final output of above code snippet:
Async: Before
Async: After
Async: function2
Async: function1
Async: function1function2 //as main thread get blocked due to await(),
it is printed at the end bcz. await() function
Ques-5: What is the suspend function in Kotlin Coroutines?
Ans-5: Suspend functions is a functions that could be started, paused and
resumed without blocking a main thread. It is only allowed to be called from other suspend functions or coroutine function.
A suspend functions is a function that can be paused and resumed
at a later time. They can execute a long running task and wait
for it to complete the operation without blocking the main thread.
Ques-6: How can you handle errors in Kotlin Coroutines?
Ans-6: In Kotlin Coroutines, we can handle exceptions using try/catch blocks.
Additionally, the Coroutines provides a features of CoroutineExceptionHandler interface can be used to define a global handler for uncaught exceptions within a coroutine scope.
Additionally, the Coroutines provides a features of CoroutineExceptionHandler interface can be used to define a global handler for uncaught exceptions within a coroutine scope.
fun main(): Unit = runBlocking {
try {
coroutineScope {
launch {
delay(1000)
throw Error("Some error")
}
launch {
delay(2000)
println("Will be printed")
}
launch {
delay(2000)
println("Will be printed")
}
}
} catch (e: Throwable) {
println("Caught $e")
}
println("Done")
}
// (1 sec)
// Caught java.lang.Error: Some error
// Done
fun main(): Unit = runBlocking {
val handler =
CoroutineExceptionHandler { ctx, exception ->
println("Caught $exception")
}
val scope = CoroutineScope(SupervisorJob() + handler)
scope.launch {
delay(1000)
throw Error("Some error")
}
scope.launch {
delay(2000)
println("Will be printed")
}
delay(3000)
}
// Caught java.lang.Error: Some error
// Will be printed
Ques-7: What is CoroutineScope and Types of CoroutineScope?
Ans-7: CoroutineScope is defined the scope of a coroutine. It provides a structured way to launch coroutines and ensures that they are automatic cancelled when the scope is cancelled.
There are basically 3 scopes in Kotlin coroutines:
- Global Scope
- LifeCycle Scope
- ViewModel Scope
When Coroutines are launched within the global scope, they live long as the application exist. If the coroutines finish it’s a job, it will be not destroyed and keep alive until the application dies.
We usually use this scope when we want to launch a long running operation on application scope so that the task will remains alive until the application killed.
GlobalScope.launch(Dispatchers.Main) {
println("loading..")
delay(3000)
println("job is done")
}
lifecycleScope.launchWhenResumed {
println("loading..")
delay(3000)
println("job is done")
}
ViewModel Scope:
viewModelScope.launch {
println("loading..")
delay(3000)
println("job is done")
}
Ques-8: What is withContext and How can we use the withContext function in Kotlin Coroutines?
Ans-8: withContext is a function used to switch context within a coroutine. It suspends the current coroutine, switches to the specified context, and resumes execution in the new context.
WithContext example:
fun startWithContextTask()
{
CoroutineScope.launch(Dispatchers.Main) {
val resultOne = withContext(Dispatchers.IO) { TaskOne() }
val resultTwo = withContext(Dispatchers.IO) { TaskTwo() }
val combinedResult = resultOne + resultTwo
}
}
Ques-9: How can we achieve parallelism using Kotlin Coroutines?
Ans-9: Parallelism in coroutines can be achieved using the async builder along with await function to await the results. Multiple asynchronous operation can be started concurrently, and their results can be combined when its needed.
import kotlinx.coroutines.*
suspend fun sendDataAndAwaitAcknowledge() = coroutineScope {
awaitAll(async {
awaitAcknowledge()
}, async {
sendData()
})
}
fun sendData() = true
fun awaitAcknowledge() = false
fun main() {
runBlocking {
println(sendDataAndAwaitAcknowledge()) // [false, true]
}
}
Ques-10: Explain the difference between launch and runBlocking in Kotlin Coroutines.
Ans-10:
launch is a coroutine builder used to start a new coroutine task asynchronously and its non blocking in nature, allowing it to run concurrently with other coroutines.
launch Example:
runBlocking is a coroutine builder that blocks the current thread until the task inside it completed. It’s mainly used for testing purpose or adapting synchronous to the asynchronous code behaviour.
runBlocking Example:
Read More: Jetpack Compose Mvvm Retrofit Example
Reference Site
here you can learn more about Kotlin Coroutines Interview Questions