← ClaudeAtlas

android-coroutines-flowlisted

Coroutines and Flow patterns for Android/KMP - dispatcher ownership, StateFlow vs SharedFlow, combine/mapLatest/debounce, cancellation, sharing, and collection in ViewModels and Compose. Use this skill whenever writing async code, exposing streams from repositories, transforming Flow, coordinating parallel work, or reviewing coroutine scope usage. Trigger on phrases like "Flow", "StateFlow", "SharedFlow", "coroutines", "dispatcher", "launch", "async", "combine", "mapLatest", "debounce", "retryWhen", or "collectLatest".
lenorebreakneck630/claude-zero-to-hero-android-KMP · ★ 1 · AI & Automation · score 64
Install: claude install-skill lenorebreakneck630/claude-zero-to-hero-android-KMP
# Android / KMP Coroutines and Flow ## Core Principles - Prefer `suspend` for one-shot work and `Flow` for streams over time. - `ViewModel` owns UI-facing coroutine scopes. - Repositories expose `Flow` only when data can change over time; otherwise return `suspend` functions. - Cancellation is expected behavior, not an error. - Never block the main thread with disk, network, or heavy CPU work. --- ## Choosing the Right API | Need | Preferred API | |---|---| | Single request/response | `suspend fun` | | Ongoing database observation | `Flow<T>` | | UI state stream | `StateFlow<T>` | | One-time events | `Channel` + `receiveAsFlow()` | | Fire-and-forget parallel child work | `coroutineScope { async { ... } }` | Do not use `LiveData` in new code. --- ## Dispatcher Ownership The class doing the blocking work is responsible for moving to the correct dispatcher. ```kotlin class ImageCompressor( private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO ) { suspend fun compress(bytes: ByteArray): ByteArray = withContext(ioDispatcher) { // blocking compression bytes } } ``` `ViewModel`s that only use `viewModelScope` should not inject dispatchers. See the **android-testing** skill for test setup with `Dispatchers.setMain(...)`. --- ## Repository Contracts Use `Flow` only when the caller should keep receiving updates: ```kotlin interface NoteRepository { fun observeNotes(): Flow<List<Note>> suspend fun refreshNotes(): EmptyResult<Da