Skip to content

SharedFlow that emits once (but buffers if there are no collectors) #3002

Open
@matejdro

Description

@matejdro

Is there a way to achieve a SharedFlow that will only emit once (replay = 0 behavior), BUT it would also buffer events until at least one collector is collecting them?

Use case for this would be sending one-off events to the UI (for example to display a one-off popup to the user). I want events to be ephemeral (if flow is collected again, they should not be replayed, so replay needs to stay at zero), but I also want events delivered in case nobody is collecting at the moment (maybe UI is in the background, so flows are not collected. But they would start getting collected as soon as UI comes into foreground)

From LiveData world, this would be similar to the SingleLiveEvent.

My current solution is to enable replay, but manually clear the replay cache after every item is emitted downstream:

private val _eventFlow = MutableSharedFlow<T>(replay = 999)
val eventFlow = _eventFlow.onEach { _eventFlow.resetReplayCache() }

This works, but I do not really like this solution, since it performs clearing on every item and it's probably not that efficient.

Another solution is using channels:

private val _eventChannel = Channel<T>(Channel.BUFFERED)
val eventFlow get() = _eventChannel.receiveAsFlow()

While above works, it only emits to one collector (if multiple collectors are awaiting for the UI events, only one will get the events), which is likely fine in the UI scenario I described above (only one screen is listening for events).

Is there a better way to achieve this that I am missing? Would it make sense to add parameter such as that to the MutableSharedFlow?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions