Individual skill
collecting-flows-safely
Use this skill to migrate Compose UI from `collectAsState()` to `collectAsStateWithLifecycle()`, hoist `Flow<T>` parameters out of composables, and apply `.conflate()` / `.distinctUntilChanged()` / `snapshotFlow` so background CPU and battery stop draining and chatty flows stop invalidating the UI per emission. Covers ViewModel `StateFlow`/`SharedFlow` consumers, sensor and location streams, and the "Flow as composable parameter" antipattern. Trigger when the user mentions `collectAsState`, `collectAsStateWithLifecycle`, lifecycle-aware flow collection, `Lifecycle.State.STARTED`, background battery drain from a Compose screen, `snapshotFlow`, `Flow` parameter on a composable, conflate, or distinctUntilChanged.
side-effects/collecting-flows-safely/SKILL.md
Source commit 1b32f81724c0d71fe9ef093ca44697f559fdab6e
What was checked
- Matches the observed repository HEAD
- Yes
- Scanner rules are current
- No
- Repository scan complete
- No
- Skill scan complete
- No
- Observed behavior
- Not checked yet
- Last checked
- Nov 6, 2026
These are observations at the recorded commit, not a guarantee of safety. Review the source before running it.
Install this skill
Choose an agent in your Stack or copy a command below. Commands fetch the pinned commit and copy only this skill directory. Existing destinations are refused. Copying a command does not install anything.
An install command is unavailable: current rules, complete repository and skill scans, an eligible behavior level and a permitted license are required.
Repository context
- Repository stars (not skill ratings)
- 526
- Repository last updated
- Jun 16, 2026
- License
- Apache-2.0
Observed agent integration: No specific integration evidence. Standard SKILL.md installation does not imply verified compatibility.
- agent-skills Repository topic
- android Repository topic
- claude Repository topic
- claude-code Repository topic
- compose Repository topic
- jetpack-compose Repository topic
- kotlin Repository topic
- llm-tools Repository topic
- recomposition Repository topic
- skydoves Repository topic
- design Derived category
- design-interface Derived category
Declared tags are partial or unavailable.
Files and excerpt
File metadata and permitted, redacted excerpts come from the recorded scan. Source links are pinned to that commit.
Read excerpt
# Collecting Flows Safely — keep upstream work tied to the UI lifecycle
`collectAsState()` keeps collecting whenever the composable is in composition, including while the app is backgrounded — that wastes CPU and battery. `collectAsStateWithLifecycle()` ties collection to a `Lifecycle.State` (default `STARTED`) so backgrounding pauses upstream work. For chatty flows, pair the consumer with `.conflate()` and `.distinctUntilChanged()` so Compose only sees meaningful changes. Skydoves hot take #4: a `Flow<T>` parameter on a composable is unstable and blocks skipping for the whole composable — collect at the caller and pass the resolved value.
## When to use this skill
- A `ViewModel` or `Repository` exposes `StateFlow<T>`, `SharedFlow<T>`, or a cold `Flow<T>` to a Compose screen.
- The user reports background battery drain, "the screen keeps working when the app is in the recents tray", or wakelock noise on logcat.
- A composable consumes sensor data, location, GPS, websocket, or animation frames coming from outside Compose.
- A composable's signature is `fun MyScreen(state: Flow<State>)` (Flow-as-parameter antipattern).
- The user asks about `collectAsState` vs `collectAsStateWithLifecycle`, or about `Lifecycle.State.STARTED` / `RESUMED` semantics.
- The user wants Compose state to drive a non-Compose subscriber (analytics on visible item index, etc.) — that is the State→Flow direction served by `snapshotFlow`.
## When NOT to use this skill