collecting-flows-safely

Migrates Android/Kotlin flows to interruptible-from-the-UI FRP with lifecycle-aware collection.

472|16|Updated Apr 29, 2026
One-click install
npx skills add https://github.com/skydoves/compose-performance-skills --skill collecting-flows-safely
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: collecting-flows-safely
Source: https://github.com/skydoves/compose-performance-skills/tree/main/side-effects/collecting-flows-safely
Command: npx skills add https://github.com/skydoves/compose-performance-skills --skill collecting-flows-safely

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Collecting flows in Compose can keep collecting even when the app is backgrounded, wasting CPU and battery. This skill guides migrating to collectAsStateWithLifecycle, hoisting Flow parameters, and applying conflate() / distinctUntilChanged() and snapshotFlow to tie work to lifecycle.

Core Features & Use Cases

  • Migrate external Flow sources to lifecycle-aware collection with collectAsStateWithLifecycle.
  • Hoist Flow<T> parameters to the caller and collect at the appropriate boundary.
  • Use .conflate() and/or .distinctUntilChanged() for high-frequency streams; leverage snapshotFlow for State-to-Flow bridges.
  • Add minActiveState awareness to focus widgets and ensure background pausing works as intended.

Quick Start

Audit your module for external flows and replace collectAsState() with collectAsStateWithLifecycle(), hoist Flow parameters to the caller, and add .conflate() / .distinctUntilChanged() where needed while using snapshotFlow for State→Flow patterns.

Frequently Asked Questions about collecting-flows-safely

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
Why does my Jetpack Compose flow keep collecting in the background and wasting battery?

Using collectAsState() keeps flows collecting even when the app is backgrounded, wasting CPU and battery. Migrating to collectAsStateWithLifecycle() ties collection to the UI lifecycle, ensuring upstream work pauses when the app enters the background.

How do I migrate from collectAsState to collectAsStateWithLifecycle in Jetpack Compose?

To migrate, replace collectAsState() with collectAsStateWithLifecycle() in your Composables, hoist Flow<T> parameters to the caller to collect at the appropriate boundary, and add .conflate() or .distinctUntilChanged() for high-frequency streams where needed.

What is the best way to bridge Compose State reads for non-UI reactions?

Use snapshotFlow to bridge State reads for non-UI reactions. snapshotFlow converts Compose State<T> changes into a Flow, allowing you to react to state changes outside of the composition lifecycle using standard Flow operators.

When should I use conflate or distinctUntilChanged with collectAsStateWithLifecycle?

Apply .conflate() and/or .distinctUntilChanged() when dealing with high-frequency streams before collecting them. These operators reduce redundant emissions and ensure the UI only processes the latest or uniquely changed values, optimizing performance.

How can I verify that upstream flow work pauses when my Compose app is backgrounded?

Verify background pausing by enforcing minActiveState usage and checking trace tooling and logcat. This confirms that upstream work tied to collectAsStateWithLifecycle actually stops when the lifecycle drops below the minimum active state.

Are there limitations to using Lifecycle.State.CREATED for flow collection in Compose?

You should avoid using Lifecycle.State.CREATED for flow collection. Enforcing minActiveState with collectAsStateWithLifecycle requires careful state management to ensure collection only happens when the lifecycle is in an appropriate active state.