Interview QuestionPractical QuestionFollow-up Questions

snapshotFlow in Jetpack Compose

skydovesJaewoong Eum (skydoves)||8 min read

snapshotFlow in Jetpack Compose

snapshotFlow is a bridge between Compose's state observation system and Kotlin's Flow API. It converts state reads that happen inside a Compose Snapshot into a cold Flow that emits whenever the observed state changes. This allows developers to apply standard Flow operators like filter, debounce, and combine to Compose state changes, which is useful for side effects like analytics, logging, or triggering backend calls in response to UI state transitions. By the end of this lesson, you will be able to:

  • Explain how snapshotFlow observes state changes through the Compose Snapshot system.
  • Describe when to use snapshotFlow versus direct state observation in Composable functions.
  • Identify how snapshotFlow integrates with LaunchedEffect for lifecycle aware collection.
  • Apply snapshotFlow with Flow operators for throttling, filtering, or combining state emissions.

How snapshotFlow Works

snapshotFlow takes a lambda block and runs it inside a Compose Snapshot. During execution, the Snapshot system records all state objects that are read. When any of those state objects change, the system re-evaluates the lambda and emits the new result to the Flow:

@Composable
fun TrackScrollPosition(listState: LazyListState) {
    LaunchedEffect(Unit) {
        snapshotFlow { listState.firstVisibleItemIndex }
            .collect { index ->
                analytics.logScrollPosition(index)
            }
    }
}

In this example, snapshotFlow observes firstVisibleItemIndex from the LazyListState. Each time the user scrolls and the first visible item changes, the Flow emits the new index. The collection happens inside a LaunchedEffect, which ties the coroutine lifecycle to the Composable's presence in the composition.

Snapshot System Integration

The Compose Snapshot system is the mechanism that tracks state reads and writes. When snapshotFlow evaluates its lambda, it creates a read only Snapshot and records every State object accessed during execution. The system then registers observers on those specific state objects.

When a state object is modified through a write operation (like updating mutableStateOf), the Snapshot system notifies snapshotFlow that one of its dependencies has changed. The lambda is re-evaluated, and if the result differs from the previous emission, the new value is sent downstream through the Flow.

This means snapshotFlow only emits when the computed result actually changes. If two different state objects change but the lambda produces the same result, no emission occurs. This built in distinctness avoids redundant processing downstream.

This interview continues for subscribers

Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.

Become a Sponsor