Kotlin中的StateFlow和SharedFlow有什么区别?

简介: - `StateFlow`持有一个最新的状态值,适合UI状态管理,新订阅者立即收到当前值。- `SharedFlow`是通用热流,用于事件总线,不保留最新状态但可配置重播。- `StateFlow`继承自`SharedFlow`,更专注于状态管理,而`SharedFlow`提供事件处理灵活性。- 示例中展示了如何`emit`新值和`collect`变化。- 选择`StateFlow`用于单最新状态共享,`SharedFlow`则适用于需要事件历史或定制策略的场景。关注公众号“AntDream”了解更多内容!

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

在Kotlin的协程库kotlinx.coroutines中,StateFlowSharedFlow是两种用于处理事件流的API,它们有相似之处,但在设计上的初衷和内在机制上有明显区别。

这次我们就对StateFlowSharedFlow进行深入对比:

StateFlowSharedFlow 概述

  • StateFlow

    • 一种用于持有单一最新状态值并发射给多个观察者的热流。适合用于状态管理场景,例如表示UI状态。
    • 和livedata比较像,有新数据可以通知collect的一方
    • 同时又具有flow的所有特点,比如可以挂起,切换线程
  • SharedFlow

    • 一种通用热流,可以发射事件流而不是仅限于持有最新状态。适合处理事件总线、观察者模式等场景。
    • 也就是一对多的关系,可以有多个collector
    • 同时又具有flow的所有特点,比如可以挂起,切换线程
    • 和上面的StateFlow不同的是,这个不能主动通知collect方,需要不断emit元素,也就是利用了flow的功能

设计初衷不同

  • StateFlow的设计是为了取代ConflatedBroadcastChannel,用于表示状态,并且总是持有最新的状态值。
  • SharedFlow的设计是为了提供一个通用的、可共享的事件流机制,支持事件的重播、缓存等。

状态持有和重播不同

  • StateFlow
    • 总是持有最新的状态值。
    • 新的观察者会立即收到当前持有的状态值。
    • 流中的每个新值都会覆盖之前的值,即只有最新的状态值会被保留。
  • SharedFlow
    • 不会持有单一最新状态值(除非配置了重播缓存)。
    • 可以配置重播机制(replay 参数)以指定新的观察者接收之前多少个已发射的值。
    • 可以配置不同的缓冲策略,如BufferOverflow来定制事件丢弃策略。

类型层次结构

  • StateFlow继承自SharedFlow,所以它是SharedFlow的一种特化实现。
public interface StateFlow<out T> : SharedFlow<T> {
    /**
     * The current value of this state flow.
     */
    public val value: T
}

应用场景

  • StateFlow:适用于状态管理场景,例如在ViewModel中表示UI状态。因为它始终持有最新的状态,能确保观察者总能获得最新的状态。

  • SharedFlow:更加灵活和通用,适用于事件处理、事件总线、消息队列等场景。尤其适合需要重播特定数量的历史事件或者处理事件丢弃政策的场景。

使用对比

StateFlow 使用示例

val _stateFlow = MutableStateFlow<Int>(0) // Initial state
val stateFlow: StateFlow<Int> = _stateFlow

// Collect values
stateFlow.collect { value ->
    println("StateFlow value: $value")
}

// Emit new state
_stateFlow.value = 1

SharedFlow 使用示例

val _sharedFlow = MutableSharedFlow<Int>(replay = 2) // Buffer size of 2
val sharedFlow: SharedFlow<Int> = _sharedFlow

// Collect values
sharedFlow.collect { value ->
    println("SharedFlow value: $value")
}

// Emit new values
_sharedFlow.emit(1)
_sharedFlow.emit(2)
_sharedFlow.emit(3)

重要的API

StateFlow
  • value:获取或设置当前的状态值。
  • collect:收集状态值的变化。
SharedFlow
  • emit:发射一个新事件。
  • collect:收集事件。
  • replayCache:获取重播缓存。

此外,两者还有collectLatest接口,下次我们再来详细对比看看

选择指南

  • 选择StateFlow:如果你的应用场景需要在多个观察者之间共享最新的状态,并且没有兴趣保留状态的历史记录,那么StateFlow是你的最佳选择。
  • 选择SharedFlow:如果你需要一个更通用的事件流机制,并且可能需要缓存和重播事件,SharedFlow提供了更强的灵活性和定制性。

对于StateFlowSharedFlow,你有什么经验和看法?欢迎留言区讨论


欢迎关注我的公众号AntDream查看更多精彩文章!

目录
相关文章
|
7月前
|
存储 机器学习/深度学习 缓存
一看就懂!图解 Kotlin SharedFlow 缓存系统
一看就懂!图解 Kotlin SharedFlow 缓存系统
200 2
|
3月前
|
Android开发 Kotlin
Android经典面试题之Kotlin的==和===有什么区别?
本文介绍了 Kotlin 中 `==` 和 `===` 操作符的区别:`==` 用于比较值是否相等,而 `===` 用于检查对象身份。对于基本类型,两者行为相似;对于对象引用,`==` 比较值相等性,`===` 检查引用是否指向同一实例。此外,还列举了其他常用比较操作符及其应用场景。
194 93
|
5月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
176 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
5月前
|
Android开发 Kotlin
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
**Kotlin中的匿名函数与Lambda表达式概述:** 匿名函数(`fun`关键字,明确返回类型,支持非局部返回)适合复杂逻辑,而Lambda(简洁语法,类型推断)常用于内联操作和高阶函数参数。两者在语法、返回类型和使用场景上有所区别,但都提供无名函数的能力。
38 0
|
7月前
|
Java Kotlin
[AIGC] Java 和 Kotlin 的区别
[AIGC] Java 和 Kotlin 的区别
|
7月前
|
Java Kotlin
[AIGC] Java 和 Kotlin 的区别
[AIGC] Java 和 Kotlin 的区别
60 0
|
存储 缓存 Android开发
Kotlin 学习笔记(六)—— Flow 数据流学习实践指北(二)StateFlow 与 SharedFlow(下)
Kotlin 学习笔记(六)—— Flow 数据流学习实践指北(二)StateFlow 与 SharedFlow(下)
192 0
|
存储 缓存 人工智能
Kotlin 学习笔记(六)—— Flow 数据流学习实践指北(二)StateFlow 与 SharedFlow(上)
Kotlin 学习笔记(六)—— Flow 数据流学习实践指北(二)StateFlow 与 SharedFlow(上)
89 0
|
Java 开发者 Kotlin
Kotlin为什么会火起来,有什么特点,跟Java区别
Kotlin为什么会火起来,有什么特点,跟Java区别
107 0
|
Java Kotlin
能说一说 Kotlin 中 lateinit 和 lazy 的区别吗?
能说一说 Kotlin 中 lateinit 和 lazy 的区别吗?