tezvyn:

Kotlin Coroutines on Android

AI-drafted, machine-checkedSource: developer.android.comadvanced
Kotlin Coroutines on Android

Kotlin coroutines let Android code write asynchronous logic that reads like sequential code, suspending instead of blocking a thread. Structured concurrency ties each coroutine to a scope, so a destroyed ViewModel cancels its children automatically.

WHY IT EXISTS Android's UI runs on a single main thread, so any slow work, network calls, database queries, disk reads, must run elsewhere and hand results back without blocking that thread. The old tools for this, AsyncTask, Handler and Looper, and raw Thread objects, all suffered from callback chains that were hard to read, easy to leak by holding an Activity reference, and painful to cancel correctly. Coroutines exist to let this asynchronous logic read like ordinary sequential code while still being non blocking underneath.

THE MENTAL MODEL Think of a coroutine as a worker who can leave a sticky note to pause a task and resume it exactly where they left off, freeing themselves to help with something else in the meantime. A suspend function is a checkpoint where that pause can happen. Nothing blocks: the thread just gets reassigned to other work until the paused coroutine's result is ready, then execution picks back up on the next line, in order, as if it had been synchronous.

HOW IT WORKS A suspend function can only be called from another suspend function or from within a CoroutineScope via launch or async. That scope carries a CoroutineContext: a Job tracks the coroutine's lifecycle and lets a parent cancel every child at once, a Dispatcher, Main, IO, or Default, decides which thread pool actually runs the code, and an optional CoroutineExceptionHandler catches uncaught errors. On Android, viewModelScope and lifecycleScope are pre wired scopes tied to a Job that cancels automatically when the ViewModel clears or the lifecycle owner is destroyed, which is structured concurrency: no coroutine can outlive the scope that launched it.

WHEN IT MATTERS It matters wherever async work must not leak past the screen that started it, a network call inside a ViewModel, a Flow collection inside a Composable. The footgun is launching from GlobalScope, which has no lifecycle tie and keeps running after the screen is gone, or mixing a regular Job with async work where one child's failure silently cancels unrelated siblings, unlike a SupervisorJob which isolates failures per child.

ONE CONCRETE EXAMPLE A ViewModel calls viewModelScope.launch to load a profile, awaiting repository.fetchUser(id) inside the block. fetchUser is a suspend function that internally switches to Dispatchers.IO for the network call, then returns to Main automatically to update a StateFlow the UI observes. If the user backs out of the screen before the response arrives, the ViewModel's onCleared cancels viewModelScope, which cancels the in flight coroutine and the underlying network call along with it.

Read the original → developer.android.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.