Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the latest value emitted by a Kotlin SharedFlow in Android?

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)
    }
}
like image 215
Vivek Modi Avatar asked Oct 26 '25 14:10

Vivek Modi


1 Answers

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.

like image 50
Tenfour04 Avatar answered Oct 29 '25 05:10

Tenfour04



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!