在Kotlin的協程庫kotlinx.coroutines
中,StateFlow
和SharedFlow
是兩種用於處理事件流的API,它們有相似之處,但在設計上的初衷和內在機制上有明顯區別。
這次我們就對StateFlow
和SharedFlow
進行深入對比:
StateFlow
和 SharedFlow
概述
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
提供了更強的靈活性和定製性。