Let's make this simple. I've one MutableSharedFlow
named sortOrder
in my ViewModel
.
private val sortOrder = MutableSharedFlow<String>(
replay = 0,
extraBufferCapacity = 1
)
I've a mapLatest
connected to the sortOrder
to refresh data whenever the sortOrder
changed.
val data = sortOrder.mapLatest {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}
I have an observer listening to data
in the activity.
viewModel.data.asLiveData().observe(this) {
Timber.d("onCreate: New data is $it")
}
and finally, I change the sortOrder
in ViewModel
's init
method
init {
sortOrder.tryEmit("year")
}
but even after changing the sortOrder
value, the mapLatest
not getting triggered. Any idea why?
I am using MutableSharedFlow
to control the replay
property to prevent executing mapLatest
body every time I rotate the screen (or when the activity recreated).
Full Source Code
PS: I am new to Flow APIs
The issue seems to be the order in which you're emitting to the flow and collecting from it (with viewModel.data.asLiveData().observe(...)
). Since you emit (with tryEmit
) in the construction of the view model, so you cannot be observing at that point. The implementation is in theory the same as this:
val sortOrder = MutableSharedFlow<String>(
replay = 0,
extraBufferCapacity = 1
)
val data = sortOrder.mapLatest {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}
sortOrder.tryEmit("year")
data.asLiveData().observe(this) {
Timber.d("onCreate: New data is $it")
}
The solution depends on your wanted behavior:
If you are okay about the same value potentially be emitted to new collectors, you can simply set reply = 1
(and then extraBufferCapacity
can be set to 0
).
The other solution is to make sure tryEmit
isn't called until after viewModel.data.asLiveData().observe(...)
is called and make sure that the activity is at least in resumed state when calling tryEmit
or else the value is ignored.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With