Reactivity
A document exposes its changes as Flow, so a UI layer (or anything else) can react
every time the stored value changes — no polling, no manual re-reads.
note.flow(): Flow<Note?> // cold; current value, then every committed write
note.stateFlow(scope): StateFlow<Note?> // hot; shared while there are subscribers
flow()
flow() is cold: it hands you the current value the moment you collect, then a
fresh value after each committed write. Emissions are conflated and fire only once a write is
durably committed — writing a different document won't wake this one up. Deleting the
document emits null:
note.flow().collect { current ->
editor.render(current)
}
stateFlow(scope)
stateFlow(scope) is hot — it needs a CoroutineScope and stays shared
while there are subscribers, which suits a ViewModel-owned stream that outlives any single
collector.
Straight into Compose
val current by note.flow().collectAsStateWithLifecycle(initialValue = note.get())
current is nullable — null simply means the note hasn't been written
yet.
How it works under the hood
MMKV has no native change-listener mechanism, so reactivity is a process-local concern: a
single change bus emits the affected document's key after every committed write or delete, and
flow() filters that bus for its own key and re-reads. See
Reactivity Model for the full mechanism, including
the important consequence that cross-process change notification is not
provided.