EventChannel

class EventChannel<T>(capacity: Int = Channel.BUFFERED, onUndeliveredElement: (T) -> Unit? = null)(source)

One-shot events (navigation, snackbars) that must not be lost when nobody is collecting yet and must be handled once. Backed by a Channel with a buffer, per FLOW_011 (a default MutableSharedFlow with replay = 0 drops events emitted before a collector attaches).

Example:

class LoginViewModel {
private val _events = EventChannel<LoginEvent>()
val events: Flow<LoginEvent> = _events.events

suspend fun onLoggedIn() { _events.send(LoginEvent.NavigateHome) }
}

Prefer send. trySend returns false when the buffer is full or the channel is closed and the event is then NOT delivered, so check its result if losing an event matters.

Delivery is at-most-once per event: an event that was already handed to a collector which is cancelled before it processes it (for example a lifecycle-aware collector stopping) is lost. Pass onUndeliveredElement to observe such events, e.g. to re-queue or log them.

Single-consumer semantics: each event is delivered to exactly one collector. With several concurrent collectors events are distributed among them, not broadcast (unlike SharedFlow). Use a single collector, or a MutableSharedFlow when every subscriber must see every event.

Rules: FLOW_011 (no replay-0 SharedFlow for one-shot events). See docs/BEST_PRACTICES_COROUTINES.md section 9.11.

Requires opting in to ExperimentalStructuredCoroutines. Thread-safe: send and trySend may be called from any thread or coroutine.

Parameters

capacity

buffer capacity, Channel.BUFFERED by default. When the buffer is full send suspends and trySend returns false, so the sender always learns about a rejected event.

onUndeliveredElement

called with an event that was accepted by the channel but could not be delivered: its collector was cancelled first, or the channel was closed without being drained. It may run concurrently and must not throw. null by default (such events are dropped).

Type Parameters

T

the event type.

See also

Constructors

Link copied to clipboard
constructor(capacity: Int = Channel.BUFFERED, onUndeliveredElement: (T) -> Unit? = null)

Properties

Link copied to clipboard
val events: Flow<T>

Events as a flow backed by receiveAsFlow; each event is received by exactly one collector. Cancelling a collector does not close the channel.

Functions

Link copied to clipboard
fun close()

Closes the channel: buffered events are still delivered, then events completes.

Link copied to clipboard
suspend fun send(event: T)

Sends event, suspending while the buffer is full.

Link copied to clipboard
fun trySend(event: T): Boolean

Sends event without suspending. Returns true if accepted, false if full or closed.