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 的擴展函數(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)文章
BootStrap中Datepicker控件帶中文的js文件
bootstrap-datepicker 是一個非常優(yōu)秀的時間選擇插件。這篇文章主要介紹了bootstrap-datepicker帶中文的js文件的相關(guān)資料,需要的朋友可以參考下2016-08-08JavaScript實現(xiàn)圖片懶加載的三種方案詳解
圖片懶加載,當(dāng)圖片出現(xiàn)在可視區(qū)域再進行加載,提升用戶的體驗,這篇文章主要為大家整理了三個常用的圖片懶加載實現(xiàn)方法,希望對大家有所幫助2023-12-12關(guān)于layui toolbar和template的結(jié)合使用方法
今天小編就為大家分享一篇關(guān)于layui toolbar和template的結(jié)合使用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09判斷javascript的數(shù)據(jù)類型(示例代碼)
這篇文章主要是對判斷javascript的數(shù)據(jù)類型(示例代碼)進行了詳細的介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12Javascript 拖拽雛形(逐行分析代碼,讓你輕松了拖拽的原理)
這篇文章主要介紹了Javascript 拖拽雛形(逐行分析代碼,讓你輕松了拖拽的原理),需要的朋友可以參考下2015-01-01