snapshotFlow
public fun <T> snapshotFlow(block: () -> T): Flow<T>
Create a Flow
from observable Snapshot
state. (e.g. state holders returned by
mutableStateOf
.)
snapshotFlow
creates a Flow
that runs block
when collected and emits the result, recording
any snapshot state that was accessed. While collection continues, if a new Snapshot
is applied
that changes state accessed by block
, the flow will run block
again, re-recording the
snapshot state that was accessed. If the result of block
is not equal to
the
previous result, the flow will emit that new result. (This behavior is similar to that of
Flow.distinctUntilChanged
.) Collection will
continue indefinitely unless it is explicitly cancelled or limited by the use of other Flow
operators.
block
is run in a read-only Snapshot
and may not modify snapshot data. If block
attempts to modify snapshot data, flow collection will fail with IllegalStateException
.
block
may run more than once for equal sets of inputs or only once after many rapid snapshot
changes; it should be idempotent and free of side effects.
When working with Snapshot
state it is useful to keep the distinction between events and
state in mind. snapshotFlow
models snapshot changes as events, but events cannot be
effectively modeled as observable state. Observable state is a lossy compression of the events
that produced that state.
An observable event happens at a point in time and is discarded. All registered observers at the time the event occurred are notified. All individual events in a stream are assumed to be relevant and may build on one another; repeated equal events have meaning and therefore a registered observer must observe all events without skipping.
Observable state raises change events when the state changes from one value to a new, unequal value. State change events are conflated; only the most recent state matters. Observers of state changes must therefore be idempotent; given the same state value the observer should produce the same result. It is valid for a state observer to both skip intermediate states as well as run multiple times for the same state and the result should be the same.
Code Examples
snapshotFlowSample
@Suppress("UNREACHABLE_CODE", "CanBeVal", "UNUSED_VARIABLE")
fun snapshotFlowSample() {
// Define Snapshot state objects
var greeting by mutableStateOf("Hello")
var person by mutableStateOf("Adam")
// ...
// Create a flow that will emit whenever our person-specific greeting changes
val greetPersonFlow = snapshotFlow { "$greeting, $person" }
// ...
val collectionScope: CoroutineScope = TODO("Use your scope here")
// Collect the flow and offer greetings!
collectionScope.launch { greetPersonFlow.collect { println(greeting) } }
// ...
// Change snapshot state; greetPersonFlow will emit a new greeting
Snapshot.withMutableSnapshot {
greeting = "Ahoy"
person = "Sean"
}
}