Coroutines Basics Interview Questions

KOTLIN › Concurrency

Walk me through what actually happens, step by step, when you call launch inside viewModelScope and the lambda calls a suspend network function.

What a strong answer covers: launch immediately returns a Job and schedules the block on the scope's dispatcher (Main.immediate by default for viewModelScope) without blocking the caller; when the coroutine hits the suspend call, the compiler-generated state machine saves its continuation and the thread is freed to do other work rather than parking. When the network call resolves, the continuation resumes, potentially on a different thread depending on the dispatcher the suspend function itself uses internally, and execution continues from that saved point.

When would you actually reach for async { }.await() immediately instead of just calling the suspend function directly? Isn't that the same thing?

What a strong answer covers: If you immediately await a single async with nothing else running concurrently, you've bought nothing over calling the suspend function directly, you've just added Deferred overhead; async only earns its keep when you start two or more of them before awaiting any, so the work genuinely overlaps in time. The trap is candidates reflexively wrapping every suspend call in async out of habit rather than because there's real concurrency to exploit.

You inherit code that calls runBlocking inside a coroutine already running on Dispatchers.Main. What's concretely wrong with this, and how would you fix it?

What a strong answer covers: runBlocking parks the current thread until its block completes, so calling it from Main blocks the UI thread for the duration, which risks an ANR and defeats the entire point of being on a coroutine in the first place; it's meant as a bridge from blocking code (like main() or a test) into suspend code, not as glue between two already-suspending contexts. The fix is to just call the suspend function directly, or use withContext if a dispatcher switch is needed, since you're already inside a coroutine and don't need to synchronously block anything.

Back to Coroutines Basics