/ 今日科技快讯 /
近日,特斯拉 CEO 埃隆・马斯克周四在 X 平台上透露,特斯拉正在改进 Optimus 机器人的设计,以解决生产过程中的关键瓶颈问题。
特斯拉的 Optimus 机器人可能是该公司未来最令人兴奋的产品之一。马斯克此前曾表示,他相信这款机器人将是有史以来最受欢迎的产品,因为其具备强大的功能。
/ 作者简介 /
大家周一好,新的一周继续努力!
本篇文章转自小墙程序员的博客,文章主要分享了 Compose 中 StateFlow 和 SharedFlow 之间的区别,相信会对大家有所帮助!
原文地址:
https://juejin.cn/post/7397019920284074022
/ 前言 /
在之前深入理解 Jetpack——LiveData 这篇文章中,我们提到过使用 LiveData 的数据丢失和数据重放的问题。因此在 Android 中,目前是更推荐使用 SharedFlow、StateFlow 来替代 LiveData。这篇文章就介绍一下,SharedFlow和 StateFlow 之间的区别。
/ Flow 与 SharedFlow 和 StateFlow 的区别 /
在开始介绍 SharedFlow和 StateFlow 之间的区别之前,我们先来看看为什么不直接使用 Flow,而是创建新的 SharedFlow和 StateFlow 呢?
这是因为普通的 Flow 数据不是共享的,每次调用 collect 都会触发新的数据流。代码如下所示:
suspend fun testCollect() {
// 打印 0 1 2
getFlow().collect {
println("first collect $it")
}
// 打印 0 1 2
getFlow().collect {
println("second collect $it")
}
}
private suspend fun getFlow() = flow {
emit(0)
emit(1)
emit(2)
}
同时,由于 Flow 是冷流,因此它需要消费端主动调用 collect 才能触发数据的流动, 而一旦消费端停止 collect 或者生产端结束,Flow 会自动关闭。除此之外, Flow 也没有数据缓存的机制,无法主动获取当前发送的数据。
与 Flow 不同的是,SharedFlow 和 StateFlow 是热流,不依赖 collect 来触发数据的流动。同时 SharedFlow 和 StateFlow 都支持数据共享的,内部也有缓存,可以获取发送的数据。如下图所示:
/ StateFlow /
StateFlow 中文翻译是状态流,主要用于共享一个状态的数据流时。在功能上,StateFlow 可以说就是一个 LiveData。
StateFlow 和 LiveData 一样数据会重放数据,代码示例如下。当 stateFlow 先发送数据 1,增加一个新的监听时,数据 1 会重新发送给这个新的监听者。需要注意的是,相同的数据是不会重放的,因为 StateFlow 内部会对数据进行判重的处理。
// 创建 StateFlow 必须需要一个默认值
val stateFlow = MutableStateFlow(0)
suspend fun testStateFlow() {
collectStateFlow()
delay(100)
stateFlow.emit(1)
// 第二次 collect 也会获取到之前发送过的 1
collectStateFlow()
}
private fun collectStateFlow() {
CoroutineScope(Dispatchers.IO).launch {
stateFlow.collect {
println("collect $it")
}
}
}
StateFlow 和 LiveData 一样数据会丢失数据。当 StateFlow 连续 emit 时,我们只会获取最新的数据 3,StateFlow 会抛弃旧的数据。
suspend fun testStateFlow() {
CoroutineScope(Dispatchers.IO).launch {
stateFlow.collect {
delay(200) // 模拟消费数据时的耗时
println("collect $it")
}
}
stateFlow.emit(1)
stateFlow.emit(2)
stateFlow.emit(3)
}
/ SharedFlow /
不同于 StateFlow 和 LiveData,默认配置下 SharedFlow 既不会重放数据,也不会丢失数据。如果你想要避免 LiveData 的重放数据和丢失数据的问题,可以使用默认配置下的 SharedFlow。
val sharedFlow = MutableSharedFlow(
replay = 0, // 重放数据个数
onBufferOverflow = BufferOverflow.SUSPEND // 缓存溢出策略
)
SharedFlow 的构造方法如上所示。它有两个参数非常重要,分别是 replay,代表重放数据个数,默认情况下为 0;另一个是 onBufferOverflow,代表缓存溢出策略,默认情况下为 BufferOverflow.SUSPEND。BufferOverflow 有三种,分别是:
BufferOverflow.SUSPEND:缓存溢出时挂起 emit 方法
BufferOverflow.DROP_LATEST:缓存溢出时丢失最新的数据
BufferOverflow.DROP_OLDEST:缓存溢出时丢失最旧的数据
SharedFlow 可以根据业务的需要对其行为进行设置。如果说你想要 SharedFlow 的行为就与 StateFlow 一样,就可以使用如下的配置,不过这种情况是直接建议使用 StateFlow。从这里可以看出,StateFlow 实际上只是 SharedFlow 的一个特例, SharedFlow 的功能更加的全面。
val shared = MutableSharedFlow(
replay = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
shared.tryEmit(initialValue) // 设置初始值
val state = shared.distinctUntilChanged() // 过滤掉相同的数据
推荐阅读:
我的新书,《第一行代码 第3版》已出版!
原创:写给初学者的Jetpack Compose教程,edge-to-edge全面屏体验
Android vold(卷管理)传记
欢迎关注我的公众号
学习技术或投稿
长按上图,识别图中二维码即可关注