kotlinx.coroutines
kotlinx.coroutines copied to clipboard
Add StateFlow<T>.onSubscription
Use case
The current SharedFlow<T>.onSubscription implementation returns a SharedFlow<T>, which means losing type information when calling it from a StateFlow<T>. It would be nice to have a StateFlow<T>.onSubscription counterpart for StateFlow<T>, thus avoiding the aforementioned issue.
The Shape of the API
Unless there are implementation details I'm unaware of, the API could be copy-pasted from the SharedFlow<T>.onSubscription implementation and adapted to work with StateFlow<T>:
public fun <T> StateFlow<T>.onSubscription(action: suspend FlowCollector<T>.() -> Unit): StateFlow<T> =
SubscribedStateFlow(this, action)
@OptIn(ExperimentalForInheritanceCoroutinesApi::class)
private class SubscribedStateFlow<T>(
private val stateFlow: StateFlow<T>,
private val action: suspend FlowCollector<T>.() -> Unit
) : StateFlow<T> by stateFlow {
override suspend fun collect(collector: FlowCollector<T>) =
stateFlow.collect(SubscribedFlowCollector(collector, action))
}
Prior Art
Sure, this makes sense, thanks! Would you like to open a PR with this code (+ documentation + tests)?
I'd be glad to! I hope to deliver the changes in the next few days.
Done!
The documentation is copy-pasted from SharedFlow<T>.onSubscription, I've only replaced the word "shared" with "state" in the first line.
About the tests, I saw that there's already testOnSubscriptionWithException (which now is using the new onSubscription), is it enough?
Good job, thanks! Let's continue under https://github.com/Kotlin/kotlinx.coroutines/pull/4380, as this starts to be about the implementation and not the issue itself.
Another useful thing to have would be to add onCompletion to StateFlow
@lemberh, it wouldn't work. SharedFlow<T>.onCompletion(action) calls action when the consumer unsubscribes, but SharedFlow is a hot flow that emits values regardless of whether there are subscribers. A version that ignores consumers and just calls action when the flow completes makes even less sense, as SharedFlow<T> never completes.