warmIn

Warm flow: a hybrid between cold and hot. The upstream does not start until the first collector asks for data, runs exactly once in scope, and memoizes every emitted value, so later (or concurrent) collectors replay the stored values and then follow the live upstream instead of re-running it.

  • Completion is memoized: collectors finish when the upstream completes (unlike shareIn, whose flow never completes).

  • An upstream failure is memoized and rethrown to every collector after the values emitted before it.

  • The upstream is never restarted and keeps running even if all collectors leave; it ends when it completes or when scope is cancelled (collectors then fail instead of hanging), including when it is cancelled before the upstream ever started. That failure is an IllegalStateException whose cause is the original CancellationException: rethrowing the cancellation itself into a collector that was not cancelled would end its coroutine silently. The same wrapping applies if the upstream throws its own CancellationException.

  • All emitted values are retained in memory: use it for finite, small flows (e.g. an expensive RPC) only.

Example:

val items = flow { emit(rpc.load()) }.warmIn(appScope)
items.collect { render(it) }
items.collect { audit(it) } // no second RPC

Pattern: warm flows, so that repeated collection of a cold flow cannot unintentionally multiply calls against a network dependency. Not tied to a lint rule: it is a server-side pattern, not a best-practice diagnostic.

Cancelling a collector cancels only that collection, never the shared upstream. Values are shared through a lock and a state flow, so any number of collectors may attach concurrently.

Requires opting in to ExperimentalStructuredCoroutines.

Receiver

the upstream flow to memoize; collected at most once.

Return

a flow that replays all stored values and then follows the live upstream.

Parameters

scope

the scope that owns the upstream collection; cancelling it ends the upstream.

See also