網站首頁 編程語言 正文
一.StateFlow的設計
StateFlow是一種單數據更新的熱流,通過emit方法更新StateFlow的數據,通過value屬性可以獲取當前的數據。在StateFlow中,核心接口的繼承關系如下圖所示:
1.StateFlow接口
StateFlow接口繼承自SharedFlow接口,代碼如下:
public interface StateFlow<out T> : SharedFlow<T> {
// 當前的數據
public val value: T
}
- 訂閱過程:在StateFlow中,每個FlowCollecter類型的對象都被稱為訂閱者。調用StateFlow類型對象的collect方法會觸發訂閱。正常情況下,訂閱不會自動結束,但訂閱者可以取消訂閱,當訂閱者所在的協程被取消時,訂閱過程就會取消。
- 冷流轉換熱流:對于一個冷流,可以通過調用stateIn方法,轉換為一個單數據更新的熱流。
- 相等判定:在StateFlow中,通過Any#equals方法來判斷前后兩個數據是否相等。當前后兩個數據相等時,數據不會被更新,訂閱者也不會處理。
- 數據緩存:StateFlow必須要有一個初始值。當新訂閱者出現時,StateFlow會將最新的數據發射給訂閱者。StateFlow只保留最后發射的數據,除此之外不會緩存任何其他的數據。同時,StateFlow不支持resetReplayCache方法。
- StateFlow并發: StateFlow中所有的方法都是線程安全的,并且可以在多協程并發的場景中使用且不必額外加鎖。
- 操作符使用:對StateFlow使用flowOn操作符、conflate操作符、參數為CONFLATED或RENDEZVOUS的buffer操作符、cancellable操作符是無效的。
- 使用場景:使用StateFlow作為數據模型,可以表示任何狀態。
- StateFlow與SharedFlow的區別:StateFlow是SharedFlow的一種特定方向的、高性能的、高效的實現,廣泛的用于單狀態變化的場景,所有與SharedFlow相關基本規則、約束、操作符都適用于StateFlow。當使用如下的參數創建SharedFlow對象,并對其使用distinctUntilChanged操作符,可以得到一個與StateFlow行為相同的SharedFlow對象:
// StateFlow
val stateFlow = MutableStateFlow(initialValue)
// 與StateFlow行為相同的SharedFlow
// 注意參數
val sharedFlow = MutableSharedFlow(
replay = 1,
extraBufferCapacity = 0,
onBufferOverflow = BufferOverflow.DROP_OLDEST)
// 設置初始值
sharedFlow.tryEmit(initialValue)
// distinctUntilChanged方法,只有當前后發射的兩個數據不同時才會將數據向下游發射
val state = sharedFlow.distinctUntilChanged()
StateFlow與ConflatedBroadcastChannel的區別:從概念上講,StateFlow與ConflatedBroadcastChannel很相似,但二者也有很大的差別,推薦使用StateFlow,StateFlow設計的目的就是要在未來替代ConflatedBroadcastChannel:
- StateFlow更簡單,不需要實現一堆與Channel相關的接口。
- StateFlow始終持有一個數據,并且無論在任何時間都可以安全的通過value屬性獲取。
- StateFlow清楚地劃分了只讀的StateFlow和可讀可寫的StateFlow。
- StateFlow對前后數據的比較是與distinctUntilChanged操作符類似的,而ConflatedBroadcastChannel對數據進行相等比較是基于標識引用。
- StateFlow不能關閉,也不能表示失敗,因此如果需要,所有的錯誤與完成信號都應該具體化。
2. MutableStateFlow接口
MutableStateFlow接口繼承自MutableSharedFlow接口與StateFlow接口,并在此基礎上定義了一個新方法compareAndSet,代碼如下:
public interface MutableStateFlow<T> : StateFlow<T>, MutableSharedFlow<T> {
// 當前數據
public override var value: T
// 通過CAS的方式,更新value
// 如果except與value相等,則將value更新為update,并返回true
// 如果except與value不相等,不做任何操作,直接返回false
// 如果except、value、update同時相等,不做任何操作,直接返回true
public fun compareAndSet(expect: T, update: T): Boolean
}
二.StateFlow的使用
1.MutableStateFlow方法
在協程中,可以通過調用MutableStateFlow方法創建一個MutableStateFlow接口指向的對象,代碼如下:
public fun <T> MutableStateFlow(value: T): MutableStateFlow<T> {
...
}
通過MutableStateFlow方法可以創建一個類型為MutableStateFlow的對象,需要提供一個參數value,作為初始值。
在并發場景下調用emit方法時,會使StateFlow的數據快速更新,對于處理數據慢的訂閱者,將會跳過這些快速更新的數據,但當訂閱者需要處理數據時,獲取的一定是最新更新的數據。
2.使用示例
代碼如下:
private suspend fun test() {
// 創建一個熱流,初始值為1
val flow = MutableStateFlow(1)
// 將MutableStateFlow對象轉換為StateFlow對象
// StateFlow對象不能調用emit方法,因此只能用于接收
val onlyReadFlow = flow.asStateFlow()
// 接收者1
// 啟動一個新的協程
GlobalScope.launch {
// 觸發并處理接收的數據
onlyReadFlow.collect {
Log.d("liduozuishuai", "test1: $it")
}
}
// 接收者2
// 啟動一個新協程
GlobalScope.launch {
// 訂閱監聽,當collect方法觸發訂閱時,會首先會調onSubscription方法
onlyReadFlow.onSubscription {
Log.d("liduozuishuai", "test2: ")
// 發射數據:2
// 向下游發射數據:2,其他接收者收不到
emit(2)
}.onEach {
// 處理接收的數據
Log.d("liduozuishuai", "test2: $it")
}.collect()
}
// 發送數據:3,多次發送
GlobalScope.launch {
flow.emit(3)
flow.emit(3)
flow.compareAndSet(3, 3)
}
}
對于上面的示例,接收者1會依次打印出:1、3,接收者2會依次打印出2、3。接收者2由于在處理onSubscription方法發射的數據2時,MutableStateFlow對象內部的數據1變成了數據3,因此在處理完數據2后,直接處理數據3。
原文鏈接:https://blog.csdn.net/LeeDuoZuiShuai/article/details/127038757
相關推薦
- 2022-06-20 golang常用加密解密算法總結(AES、DES、RSA、Sha1、MD5)_Golang
- 2022-03-28 用python實現九九乘法表實例_python
- 2022-09-16 Python?docx庫刪除復制paragraph及行高設置圖片插入示例_python
- 2023-05-07 oracle中如何保留兩位小數_oracle
- 2022-02-23 去除type=“number“輸入框聚焦時的上下箭頭
- 2023-01-08 Go設計模式原型模式考查點及使用詳解_Golang
- 2022-05-04 python工具dtreeviz決策樹可視化和模型可解釋性_python
- 2023-04-10 Python中mmap模塊處理大文本的操作方法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支