Kotlin-StateFlow

58 阅读2分钟

前言

StateFlow 是ShareFlow的replay=1,必须有默认值,emit方法永远不会挂起,订阅时总是能够拿到它的最新的一个元素。

fun main() {
    runBlocking {
        val stateFlow = MutableStateFlow(-1)
        launch {
            repeat(3) {
                delay(10)
                println("threadName:${Thread.currentThread().name} emit:$it time:${System.currentTimeMillis()}")
                stateFlow.emit(it)
            }
            stateFlow.collect {
                println("threadName:${Thread.currentThread().name} collect:$it time:${System.currentTimeMillis()}")
            }
        }
    }
}
输出:
threadName:Test worker @coroutine#2 emit:0 time:1712719296772
threadName:Test worker @coroutine#2 emit:1 time:1712719296787
threadName:Test worker @coroutine#2 emit:2 time:1712719296803
threadName:Test worker @coroutine#2 collect:2 time:1712719296807

在同一个协程2中进行先emit再collect。则只会collect最后一个数据。

fun main() {
    runBlocking {
        val stateFlow = MutableStateFlow(-1)
        launch {
            delay(100)
            repeat(3) {
                println("threadName:${Thread.currentThread().name} emit:$it time:${System.currentTimeMillis()}")
                stateFlow.emit(it)
            }
        }
        launch {
            stateFlow.collect {
                println("threadName:${Thread.currentThread().name} collect:$it time:${System.currentTimeMillis()}")
            }
        }
    }
}
输出:
threadName:Test worker @coroutine#3 collect:-1 time:1712719030700
threadName:Test worker @coroutine#2 emit:0 time:1712719030810
threadName:Test worker @coroutine#2 emit:1 time:1712719030811
threadName:Test worker @coroutine#2 emit:2 time:1712719030811
threadName:Test worker @coroutine#3 collect:2 time:1712719030811

先collect到默认值-1;在协程2中连续emit 3个值,在协程2 collect只收到最后一个值,中间值全部丢弃了。

fun main() {
    runBlocking {
        val stateFlow = MutableStateFlow(-1)
        launch {
            repeat(3) {
                delay(10)
                println("threadName:${Thread.currentThread().name} emit:$it time:${System.currentTimeMillis()}")
                stateFlow.emit(it)
            }
        }
        launch {
            stateFlow.collect {
                println("threadName:${Thread.currentThread().name} collect:$it time:${System.currentTimeMillis()}")
            }
        }
    }
}
输出:
threadName:Test worker @coroutine#3 collect:-1 time:1712719168577
threadName:Test worker @coroutine#2 emit:0 time:1712719168596
threadName:Test worker @coroutine#3 collect:0 time:1712719168597
threadName:Test worker @coroutine#2 emit:1 time:1712719168612
threadName:Test worker @coroutine#3 collect:1 time:1712719168612
threadName:Test worker @coroutine#2 emit:2 time:1712719168627
threadName:Test worker @coroutine#3 collect:2 time:1712719168627

如果对emit添加10ms延迟,则中间值全部collect到了。

从上面看出StateFlow更适合更新状态(中间值可能丢弃,但是保证最新值能collect到)