question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Most of the times sharedFlow doesn't emit the initial value

See original GitHub issue

Hi,

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:open
  • Created 3 years ago
  • Comments:14 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
elizarovcommented, Dec 4, 2020

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.

1reaction
elizarovcommented, Dec 2, 2020

In your particular architecture the easiest solution I see if to inject InitialAction downstream from shareIn operator, not upstream of it. You can also change replay to zero:

stream.shareIn(scope, SharingStarted.Eagerly).onStart { emit(Action.InitialAction) }

This way, every subscriber is guaranteed to get InitialAction first, followed by further (shared) actions.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found