Coroutines
Kotlin's coroutines, with the ceremony removed: io, cpu and main for picking a thread, and $scope() for work you need to be able
to cancel.
suspend functions
suspend works exactly as it does in Kotlin:
suspend fun loadData() { … } A suspend function in a component's script is one of the things that promotes it
to a ViewModel, so its work survives rotation. See State & Reactivity.
See it happen
Add a suspend fun and watch the whole file grow a ViewModel.
var count = 0
<Button onClick={() => count++}>Increment</Button>No suspend function, so count lives in remember — simple, but a rotation loses it.
Choosing a thread
Three blocks, named for what the work is rather than which dispatcher backs it:
<Button onClick={() => io { loadData() }}>Load</Button>
<Button onClick={() => cpu { process() }}>Process</Button>
<Button onClick={() => main { update() }}>Update</Button> | Block | Dispatcher | For |
|---|---|---|
io | Dispatchers.IO | Network, disk, database — work that waits |
cpu | Dispatchers.Default | Parsing, sorting, image work — work that computes |
main | Dispatchers.Main | Touching UI from inside background work |
Each compiles to a launch on a scope tied to the composable:
dispatcherScope.launch(Dispatchers.IO) { loadData() } 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.
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 / $layoutData — loading before a screen renders