Kotlin flows SharedFlow not received in collectInLifeCycle inside Fragment

48 Views Asked by At

I am observing inside a fragment the events of a sharedflow such as this:

myEvent.collectInLifeCycle(viewLifecycleOwner) { event ->
       when (state) {
         //check the event. The event emited form onStart is never reached here :(             
       }
}

Whereas in the viewmodel I have

private val _myEvent = MutableSharedFlow<MyEvent>()
    val myEvent: SharedFlow<MyEvent> = _myEvent

fun loadData() =
        viewModelScope.launch {
            getDataUseCase
                .safePrepare(onGenericError = { _event.emit(Event.Error(null)) })
                .onStart { _event.emit(Event.Loading) }
                .onEach { result ->
                    result.onSuccess { response -> 
                      _event.emit(Event.Something)
                    }
                }
                .launchIn(viewModelScope)
        }

So the problem is that only the Event.Something is the one being properly collected from the fragment, whereas _event.emit(Event.Loading) is not being collected... If I debug it goes to the onStart, but it is never called in the fragment.

1

There are 1 best solutions below

2
Tenfour04 On

Your SharedFlow needs to have a replay so that collectors always get at least the most recent value. Otherwise, if you emit to the Flow before the collector is registered, it will never see anything emitted. Do this:

private val _myEvent = MutableSharedFlow<MyEvent>(replay = 1)

Personally, unless I'm missing some detail here that would change my mind, I would simplify all your code to avoid having to manually call loadData(). Something like this but I'm guessing a bit because I don't know all your types and functions.

val myEvent: SharedFlow<MyEvent> = flow {
    emit(Event.Loading)
    emitAll(
        getDataUseCase
            .transform { result ->
                result.onSuccess { response -> 
                    emit(Event.Something)
                }
            }
            .catch { error -> emit(Event.Error(null)) }
    )
}.shareIn(viewModelScope, SharingStarted.Lazily, replay = 1)