Most of the times sharedFlow doesn't emit the initial value
See original GitHub issueHi,
I have been testing sharedFlow over the weekend and I got a strange behaviour with it. I have got some code like that:
class MainScreen(
private val incrementCounterUseCase: IncrementCounterUseCase,
private val loadMovieListUseCase: LoadMovieListUseCase
) : Screen<MainInput, MainOutput>() {
override fun output(): Flow<MainOutput> = input.receiveAsFlow()
.let(inputToAction())
.let { stream ->
val upstream = stream.shareIn(scope, SharingStarted.Lazily)
listOf(
upstream.filterIsInstance<Action.InitialAction>().let(loadMovieListUseCase()),
upstream.filterIsInstance<Action.IncrementNumber>().let(incrementCounterUseCase())
)
.merge()
}
companion object {
fun inputToAction() = FlowTransformer<MainInput, Action> { flow ->
flow.map { input ->
when (input) {
MainInput.Click -> Action.IncrementNumber
MainInput.RetryClicked -> Action.InitialAction
}
}.onStart {
emit(Action.InitialAction)
}
}
}
}
If I debug using doOnEach, I was able to see that the Action.InitialAction is emitted every time. However after the shareIn, the stream is not always setup and the function loadMovieListUseCase doesn’t receive that InitialAction. And the strange part, it is that the next event on the stream, always respond properly. I have tried both SharingStarted.Lazily and Eagerly, it seems that eagerly make it worth.
Maybe I am missing something, note that I have also tried with coroutine 1.4.0 and it didn’t fixed the issue.
Thank you for your time!
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (6 by maintainers)
Top Results From Across the Web
kotlin - SharedFlow always missing out on the initial value
I am trying to understand how SharedFlow works, but notice that the 1st emitted value is always not collected by the consumer.
Read more >MutableSharedFlow is kind of complicated | by Lukas Vyletel
What tryEmit method does, in order to not block thread until an event is collected, is that it sends a value to MutableSharedFlow...
Read more >MutableSharedFlow - Kotlin
The MutableSharedFlow interface is not stable for inheritance in 3rd party ... To reset a shared flow to an initial value, emit the...
Read more >Kotlin flows on Android - Android Developers
In coroutines, a flow is a type that can emit multiple values sequentially, ... operator to a stream does not start the flow...
Read more >Smarter Shared Kotlin Flows - Christophe Beyls - Medium
Flow and SharedFlow do not support the Android Lifecycle class directly, ... SharingStarted is used to emit a Flow of START and STOP...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
In general – no. The design of the flow is very simple and it does not support the concept of “subscription” in general case. For an arbitrary flow you cannot tell when the “subscription” had happened, so that’s why
onSubscribe
operator is only supported by special, shared flows.In your particular architecture the easiest solution I see if to inject
InitialAction
downstream fromshareIn
operator, not upstream of it. You can also change replay to zero:This way, every subscriber is guaranteed to get
InitialAction
first, followed by further (shared) actions.