I'm working with Kotlin SharedFlows and I'm trying to get only the latest value emitted by the flow. I've tried using the last() operator, but it's not working as expected.
main
fun main(): Unit = runBlocking {
val eventBus = EventBus()
launch {
val latestValue = eventBus.value.lastOrNull()
if (latestValue != null) {
println("Latest value: $latestValue")
}
}
launch {
repeat(5) {
eventBus.increment(it)
}
}
launch {
delay(5.seconds)
(5..10).forEach {
eventBus.increment(it)
}
}
}
EventBus
class EventBus {
private val _value = MutableSharedFlow<Int>()
val value: SharedFlow<Int> = _value.asSharedFlow()
suspend fun increment(number: Int) {
_value.emit(number)
}
}
Explanation
I want to capture only the latest value emitted by the observable. For instance, if the observable emits values from 0 to 4, and then pauses for a while, followed by values from 5 to 10, I want to retain only the final value for each interval. For the initial interval (0 to 4), I want to store 4, and for the second interval (5 to 10), I want to store 10. Is this achievable?
Thanks
UPDATE
After @Tenfour04 suggestion I tried some code but it doesn't print 2nd interval latest value.
fun main(): Unit = runBlocking {
val eventBus = EventBus()
launch {
repeat(5) {
eventBus.increment(it)
}
}
launch {
delay(5.seconds)
(5..10).forEach {
delay(100)
eventBus.increment(it)
}
}
launch {
val latestValue = eventBus.value.replayCache.firstOrNull()
if (latestValue != null) {
println("Latest value: $latestValue")
}
}
}
class EventBus {
private val _value = MutableSharedFlow<Int>(replay = 1)
val value: SharedFlow<Int> = _value.asSharedFlow()
suspend fun increment(number: Int) {
_value.emit(number)
}
}
last() works on any flow, and it under the hood collects the entire flow and then outputs the last value collected. Therefore, it is a function that can never return if called on an infinite flow. SharedFlows are always infinite.
To get the most recent value of a SharedFlow, the SharedFlow should have a replay of 1 and then you can call first() on it to get the most recent value. If there is no replay, the SharedFlow has no record of its most recent value so it is impossible to retrieve it.
But if nothing has posted to the flow yet, you will actually be getting the next value.
StateFlow may be better suited for what you’re trying to do, because it guarantees there is always a current value that you can check instantly using its value property.
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