https://kotlinlang.org logo
Title
l

louiscad

05/11/2022, 4:37 PM
Hello folks! I had to map a
StateFlow
to another
StateFlow
with a synchronous operation (it's quite cheap, it's only one object allocation), and I didn't want to have to link it to a
CoroutineScope
this time, so I wrote this
mapSync
extension function, which you can criticize, and copy at will. I'm using it in a single-thread context, but I think it'd work just fine in multi-thread so long as the mapping operation is cheap and doesn't cause heavy recomputations on concurrent accesses.
import kotlinx.coroutines.flow.*

fun <T, R> StateFlow<T>.mapSync(transform: (T) -> R): StateFlow<R> = object : StateFlow<R> {

    override val replayCache: List<R> get() = listOf(value)

    override suspend fun collect(collector: FlowCollector<R>): Nothing {
        this@mapSync.collect {
            collector.emit(transform(it))
        }
    }

    private var lastUpstreamValue = this@mapSync.value

    override var value: R = transform(lastUpstreamValue)
        private set
        get() {
            val currentUpstreamValue: T = this@mapSync.value
            if (currentUpstreamValue == lastUpstreamValue) return field
            field = transform(currentUpstreamValue)
            lastUpstreamValue = currentUpstreamValue
            return field
        }
}
I hope it's helpful to some of you!
:nice: 4
r

Robert Jaros

05/11/2022, 4:49 PM
StateFlow
interface is still not stable for inheritance, isn't it?
l

louiscad

05/11/2022, 5:23 PM
I'm not sure if Flow is still in that case, but StateFlow is not unstable for inheritance.
r

Rick Clephas

05/11/2022, 7:45 PM
It's actually not stable for inheritance in 3rd party libraries (just like all other Flow interfaces), but it should be fine in your application code (although you can expect new methods in the future). https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/