Coroutines
Kotlin's coroutines, with one rule: call a suspend function from anywhere, and
it runs. Nothing wraps it, and nothing chooses a thread for you unless you ask.
suspend functions
suspend works exactly as it does in Kotlin:
suspend fun loadData() { … } Call it from a handler, $onMount, or another function, and the compiler
launches it wherever it's referenced:
suspend fun loadData() { … }
<Button onClick={loadData}>Load</Button> See it happen
Add a suspend fun and watch the click handler launch it.
import $lib.components.ui.Button
var count = $state(0)
<Button onClick={() => count++}>Increment</Button>count is an Int, so it lives in rememberSaveable and survives a rotation.
Naming a thread yourself
For CPU-bound work — parsing, sorting, image processing — name the dispatcher directly, with Kotlin's own API:
var processed: Data? = $state(null)
<Button onClick={() => process()}>Process</Button>
suspend fun process() {
processed = withContext(Dispatchers.Default) {
processLargeDataset()
}
} There is nothing else to name. A suspend call is IO-bound or CPU-bound the same
way it would be in a plain Kotlin app — withContext is how you say which, and
it is the only spelling.
Cancellable work
$scope() gives you a scope you hold onto, for work a user can start and then
change their mind about:
val uploadScope = $scope()
<Button onClick={() => uploadScope.launch { upload() }}>Upload</Button>
<Button onClick={() => uploadScope.cancel()}>Cancel</Button> It compiles to rememberCoroutineScope(), so it is scoped to the composable and
anything still running is cancelled when the screen leaves. Use it for a choice, not a
thread — an ordinary suspend call needs no scope at all.
Work that should outlive the screen
A coroutine dies with the composable that launched it. Uploading a photo, syncing a feed, or anything that must finish whether or not the user stays on the screen belongs in a worker instead, which Android schedules and retries:
$dispatch(api.upload, name: "upload-$id", constraints: ["wifi"]) runBlocking, Thread.sleep and suspend outright, because
it has sixty seconds before Android reports an ANR.See Also
- $onMount / $onDispose — where most loading starts
- $fetch — suspend HTTP with disk caching
- $dispatch / $periodic — background work with constraints
- $data — loading before a screen renders