50 Android Kotlin Coroutine Interview Questions & Answers
- Q1: What is a coroutine in Kotlin?
A: A coroutine is a lightweight thread-like construct for asynchronous programming in Kotlin. It allows writing non-blocking code sequentially.
- Q2: Difference between
launch and async?
A: launch returns a Job and is used for fire-and-forget tasks; async returns a Deferred and is used when you need a result.
- Q3: What is
runBlocking?
A: A blocking coroutine builder that blocks the current thread until all coroutines inside it complete, commonly used in main() or tests.
- Q4: What is
Dispatchers.Main?
A: Dispatcher for Android main/UI thread. Use it to update UI from coroutines.
- Q5: What is
Dispatchers.IO?
A: Dispatcher optimized for IO-bound tasks like network and database operations.
- Q6: What is
Dispatchers.Default?
A: Dispatcher optimized for CPU-intensive tasks like sorting, calculations, or parsing.
- Q7: How do you cancel a coroutine?
A: By calling job.cancel(). If the coroutine is cooperative, it will stop at the next suspension point.
- Q8: What is
isActive used for?
A: To check if a coroutine is still active, usually inside loops for cooperative cancellation.
- Q9: What is
Job in coroutines?
A: A handle to manage coroutine lifecycle — it allows cancelling, checking status, or joining.
- Q10: Difference between
CoroutineScope and GlobalScope?
A: CoroutineScope is structured and tied to lifecycle; GlobalScope is global, lives until the app stops, and is not recommended for Android.
- Q11: What is structured concurrency?
A: Parent coroutines manage children — when parent cancels, all children are cancelled automatically.
- Q12: What is
SupervisorJob?
A: A job where children are independent — failure of one child does not cancel siblings.
- Q13: Difference between
supervisorScope and coroutineScope?
A: supervisorScope isolates failures of children; coroutineScope cancels all children if one fails.
- Q14: How to handle uncaught exceptions in coroutines?
A: Use CoroutineExceptionHandler for launch coroutines; for async, exceptions are thrown on await().
- Q15: Difference between
cancel() and cancelAndJoin()?
A: cancel() requests cancellation; cancelAndJoin() requests cancellation and waits until the coroutine finishes.
- Q16: What is
withContext?
A: A suspending function that switches the coroutine context for a block of code and returns the result.
- Q17: Can you switch dispatchers inside a coroutine?
A: Yes, using withContext(Dispatchers.IO) or any other dispatcher.
- Q18: Difference between
launch(start=LAZY) and launch(start=DEFAULT)?
A: LAZY starts only when start(), join() or await() is called; DEFAULT starts immediately.
- Q19: What is
yield() in coroutines?
A: Suspends the current coroutine to give other coroutines a chance to run.
- Q20: Difference between
async and runBlocking?
A: async runs concurrently and returns a Deferred; runBlocking blocks the current thread until coroutine finishes.
- Q21: How does coroutine cancellation propagate?
A: Cancellation propagates from parent to children automatically in structured concurrency.
- Q22: Difference between
Unconfined and Main dispatcher?
A: Unconfined starts in caller thread and may resume in a different thread; Main always runs on UI thread.
- Q23: Can you cancel
async coroutine?
A: Yes, by calling deferred.cancel(). Exception occurs if await() is called after cancellation.
- Q24: Difference between
Job and Deferred?
A: Job is for lifecycle management; Deferred also returns a value via await().
- Q25: How do you handle cancellation in loops?
A: Check isActive periodically and exit the loop to stop gracefully.
- Q26: What are coroutine builders in Kotlin?
A: launch, async, runBlocking, and withContext are main builders.
- Q27: Difference between
launch and launch { GlobalScope.launch { ... } }?
A: GlobalScope.launch is not tied to structured concurrency, may leak coroutines; normal launch is scoped and managed.
- Q28: What is
join() used for?
A: Suspends the calling coroutine until the target coroutine completes.
- Q29: Can you run multiple coroutines concurrently?
A: Yes, launch multiple coroutines inside a scope; they run concurrently.
- Q30: Difference between
coroutineScope and runBlocking?
A: coroutineScope is suspending and non-blocking; runBlocking blocks the current thread.
- Q31: How do you propagate exceptions in coroutines?
A: In launch, unhandled exceptions cancel the parent; in async, exceptions are propagated on await().
- Q32: Can you launch a coroutine on a custom thread pool?
A: Yes, using newSingleThreadContext or Executor.asCoroutineDispatcher().
- Q33: Difference between
GlobalScope.launch and lifecycleScope.launch in Android?
A: lifecycleScope is tied to Activity/Fragment lifecycle; GlobalScope lives until app exits.
- Q34: What is
Dispatchers.Default used for?
A: For CPU-intensive operations like sorting, parsing, or heavy computation.
- Q35: Can you call
withContext from launch coroutine?
A: Yes, it suspends the coroutine and switches context for that block.
- Q36: How do you make a coroutine lazy?
A: launch(start=CoroutineStart.LAZY) { ... }
- Q37: Difference between
Atomic and Lazy start modes?
A: ATOMIC starts immediately and cannot be cancelled until first suspension; LAZY starts only on explicit start or join.
- Q38: Can coroutines replace RxJava?
A: Yes, Kotlin coroutines with Flow can replace RxJava for asynchronous streams in modern Android apps.
- Q39: What is
flow in coroutines?
A: Cold asynchronous data stream that supports backpressure and can emit multiple values over time.
- Q40: Difference between
SharedFlow and StateFlow?
A: StateFlow holds a single state and emits updates; SharedFlow is hot and can have multiple subscribers.
- Q41: What is
Dispatchers.Unconfined?
A: Starts in the caller thread, resumes in the thread determined by the suspending function.
- Q42: Can coroutines be cancelled from outside?
A: Yes, by cancelling the parent job or the coroutine’s Job object.
- Q43: Difference between blocking and suspending functions?
A: Blocking functions block the thread; suspending functions suspend the coroutine without blocking the thread.
- Q44: How do you wait for multiple coroutines to finish?
A: Use joinAll(job1, job2, ...) or coroutineScope { ... } to wait structuredly.
- Q45: Difference between
supervisorScope and SupervisorJob?
A: supervisorScope is a suspending function; SupervisorJob is a Job instance that can be added to a scope.
- Q46: Can you cancel a coroutine from inside itself?
A: Yes, call coroutineContext.cancel() or currentCoroutineContext().cancel().
- Q47: Difference between
Dispatchers.IO and Dispatchers.Default?
A: IO is optimized for blocking IO tasks; Default is optimized for CPU-intensive work.
- Q48: What is
yield() used for?
A: Suspends the current coroutine to allow other coroutines to execute.
- Q49: Difference between
Job.cancel() and Thread.interrupt()?
A: Job.cancel() is cooperative; Thread.interrupt() forces interruption at thread level.
- Q50: How do you handle exceptions in
async coroutines?
A: Exceptions are propagated when await() is called; can use try-catch around await() to handle them.