Kotlin Coroutines Basics
Async programming on Android the modern way — suspend, scopes, dispatchers.
What You'll Learn
- Understand what coroutines are and why they replace AsyncTask
- Use suspend functions and launch / async builders
- Pick the right Dispatcher for each job
- Use viewModelScope and lifecycleScope safely
- Handle errors with try/catch and CoroutineExceptionHandler
Prerequisites
- Kotlin basics (data classes, lambdas, extension functions)
- Basic Android / ViewModel knowledge
Step-by-Step Guide
Step 1
1. What Are Coroutines?
Coroutines are suspendable computations. Unlike threads, they're lightweight — you can run thousands concurrently on a handful of OS threads. A suspend function can pause without blocking the thread, letting other work proceed. The Kotlin compiler transforms suspend functions into state machines under the hood. Add dependencies: implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.x'
Step 2
2. launch vs async
launch starts a coroutine and returns a Job (fire-and-forget). async starts a coroutine and returns a Deferred<T> — await() the result when needed. Use launch for operations with no return value (writing to DB, logging). Use async + await when you need a result or want to run multiple operations concurrently and combine results.
Step 3
3. Dispatchers
Dispatchers.Main: UI updates only — runs on the Android main thread. Dispatchers.IO: network calls, file/database I/O (optimized pool of 64 threads). Dispatchers.Default: CPU-intensive work (sorting, parsing). Switch with withContext(Dispatchers.IO) { ... } inside a coroutine without blocking. Never do network I/O on Dispatchers.Main.
Step 4
4. Structured Concurrency with Scopes
Always launch coroutines in a scope. viewModelScope cancels all coroutines when the ViewModel is cleared — no memory leaks. lifecycleScope (in Activity/Fragment) respects the lifecycle. GlobalScope is almost always wrong — it ignores structured concurrency. If a child coroutine fails, the scope propagates the failure and cancels siblings.
Step 5
5. Error Handling
Wrap suspend calls in try/catch just like synchronous code. For launch, unhandled exceptions propagate to the CoroutineExceptionHandler installed on the scope. For async, exceptions are thrown when you call await() — wrap that in try/catch. CancellationException is special — don't catch and swallow it, as that breaks cancellation. Rethrow it if you catch Throwable.
Further Reading & Resources
Ready to put this into practice?
Apply for a real App Development internship and ship production projects with mentorship.
