Kotlin中?StateFlow?或?SharedFlow?的區(qū)別解析
StateFlow 和 SharedFlow 是 Kotlin 協(xié)程(Coroutines) 提供的兩種 響應(yīng)式數(shù)據(jù)流(Reactive Streams),用于在應(yīng)用程序中處理異步數(shù)據(jù)流,類似于 RxJava 的 Observable 或 Flowable,但更輕量且與 Kotlin 協(xié)程深度集成。
1. StateFlow(狀態(tài)流)
StateFlow 是一種 熱流(Hot Flow),它會存儲當(dāng)前的狀態(tài)值,并在狀態(tài)變化時通知所有訂閱者。
特點
- 必須有初始值(不能為空)。
- 只保留最新的值(新訂閱者會立即收到當(dāng)前值)。
- 是
SharedFlow的特殊情況(相當(dāng)于replay=1的SharedFlow)。 - 適用于 UI 狀態(tài)管理(如
ViewModel暴露 UI 狀態(tài))。
示例
// 定義 StateFlow(通常在 ViewModel 中)
private val _counterState = MutableStateFlow(0) // 初始值 0
val counterState: StateFlow<Int> = _counterState.asStateFlow()
// 更新值
fun increment() {
_counterState.value++ // 自動通知所有訂閱者
}
// 在 Activity/Fragment 中監(jiān)聽
lifecycleScope.launch {
viewModel.counterState.collect { value ->
textView.text = "Count: $value"
}
}2. SharedFlow(共享流)
SharedFlow 也是一種 熱流,但它不存儲狀態(tài),而是用于 廣播事件(如一次性事件、通知等)。
特點
- 沒有初始值(可以發(fā)送任意數(shù)量的數(shù)據(jù))。
- 可以配置緩存大小(
replay控制新訂閱者能收到多少歷史數(shù)據(jù))。 - 適用于事件總線、通知等場景(如 Toast 消息、導(dǎo)航事件)。
示例
// 定義 SharedFlow(通常在 ViewModel 中)
private val _toastEvent = MutableSharedFlow<String>() // 無初始值
val toastEvent: SharedFlow<String> = _toastEvent.asSharedFlow()
// 發(fā)送事件
fun showToast(message: String) {
viewModelScope.launch {
_toastEvent.emit(message) // 發(fā)送事件
}
}
// 在 Activity/Fragment 中監(jiān)聽
lifecycleScope.launch {
viewModel.toastEvent.collect { message ->
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}StateFlow vs SharedFlow
| 特性 | StateFlow | SharedFlow |
|---|---|---|
| 初始值 | ? 必須有 | ? 不需要 |
| 緩存歷史數(shù)據(jù) | 僅最新值 | 可配置 (replay) |
| 適用場景 | UI 狀態(tài)管理(如 LiveData 替代) | 事件總線、通知 |
| 是否熱流 | ? 是 | ? 是 |
| 線程安全 | ? 是(協(xié)程作用域內(nèi)) | ? 是 |
因此,以下面這段代碼舉例:
/**
* 應(yīng)用中心數(shù)據(jù)變化,更新應(yīng)用中心小組件的顯示
*/
private fun WidgetSelectorViewModel.observerAppList() = coroutineScope.launch {
appWidgets.onEach { list ->
Log.d(TAG, "observerAppList setDataList")
gridAdapterApp.setDataList(list)
appItemBinding?.groupNoData?.isVisible = list.isEmpty()
}.launchIn(coroutineScope)
} 功能總結(jié):
這段代碼的主要作用是監(jiān)聽?wèi)?yīng)用小組件列表(appWidgets)的變化,每當(dāng)列表更新時:
將新列表設(shè)置給網(wǎng)格適配器(gridAdapterApp)以更新UI
根據(jù)列表是否為空來顯示或隱藏"無數(shù)據(jù)"的提示
所有這些操作都在協(xié)程中異步執(zhí)行
這是一種典型的響應(yīng)式編程模式,通過觀察數(shù)據(jù)流來自動更新UI,避免了手動刷新數(shù)據(jù)的需要。
首先是函數(shù)定義:
private fun WidgetSelectorViewModel.observerAppList() = coroutineScope.launch {- 這是一個 WidgetSelectorViewModel 的擴(kuò)展函數(shù)
- 函數(shù)是私有的(private)
- 返回一個協(xié)程啟動器(launch)
- 函數(shù)名為 observerAppList(),表示它用于觀察應(yīng)用列表
其次是函數(shù)體:
appWidgets.onEach { list ->
gridAdapterApp.setDataList(list)
appItemBinding?.groupNoData?.isVisible = list.isEmpty()
}.launchIn(coroutineScope)appWidgets可能是一個StateFlow或SharedFlow(取決于它的定義)。onEach會在每次數(shù)據(jù)變化時執(zhí)行,更新 UI。launchIn(coroutineScope)表示在指定的協(xié)程作用域內(nèi)啟動這個流。
總結(jié)
StateFlow→ 用于 UI 狀態(tài)管理(如LiveData的替代)。SharedFlow→ 用于 事件通知(如 Toast、導(dǎo)航事件)。- 兩者都是 熱流,即使沒有訂閱者也會發(fā)送數(shù)據(jù)。
- 通常結(jié)合
ViewModel+collect使用,實現(xiàn)響應(yīng)式 UI 更新。
如果你的 appWidgets 是一個應(yīng)用列表的狀態(tài),那它更適合用 StateFlow;如果是臨時事件(如刷新完成通知),則更適合 SharedFlow。
到此這篇關(guān)于Kotlin中 StateFlow 或 SharedFlow 的區(qū)別的文章就介紹到這了,更多相關(guān)Kotlin StateFlow 或 SharedFlow 的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA實現(xiàn)PDF轉(zhuǎn)HTML文檔的示例代碼
本文是基于PDF文檔轉(zhuǎn)PNG圖片,然后進(jìn)行圖片拼接,拼接后的圖片轉(zhuǎn)為base64字符串,然后拼接html文檔寫入html文件實現(xiàn)PDF文檔轉(zhuǎn)HTML文檔,感興趣的可以了解一下2021-05-05
如何利用Spring?MVC實現(xiàn)RESTful風(fēng)格
這篇文章主要介紹了如何利用Spring?MVC實現(xiàn)RESTful風(fēng)格,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
springBoot使用openfeign來遠(yuǎn)程調(diào)用的實現(xiàn)
這篇文章主要介紹了springBoot使用openfeign來遠(yuǎn)程調(diào)用的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
spring中REST和RESTful的區(qū)別以及基本實現(xiàn)
本文主要介紹了spring中REST和RESTful的區(qū)別以及基本實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
詳解Springboot整合Dubbo之代碼集成和發(fā)布
本篇文章主要介紹了Springboot整合Dubbo之代碼集成和發(fā)布,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
Spring-Boot 集成Solr客戶端的詳細(xì)步驟
本篇文章主要介紹了Spring-Boot 集成Solr客戶端的詳細(xì)步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11

