Android StateFlow详解
轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/zhaoyanjun6/article/details/121913352
本文出自【趙彥軍的博客】
文章目錄
- 系列文章
- 一、冷流還是熱流
- StateFlow
- 1. StateFlow使用
- 2. 和LiveData比較
- 3. 如何解決開頭的問題
系列文章
Android SharedFlow詳解
Android StateFlow詳解
簡(jiǎn)單描述一下:
點(diǎn)擊圖中的皇冠按鈕,會(huì)彈出 Nike、Adidas 和 其他 品牌的按鈕,選中之后,頁面中數(shù)據(jù)源只會(huì)包含該品牌的數(shù)據(jù)。
簡(jiǎn)單看一下,原來的結(jié)構(gòu),使用的 LiveData:
class MainViewModel : ViewModel() {private val selectedBrand = MutableLiveData<String>()// 2. 數(shù)據(jù)源根據(jù)selectedBrand自動(dòng)發(fā)生切換val shoes: LiveData<Shoe> = selectedBrand.switchMap {// ... 切換成對(duì)應(yīng)的數(shù)據(jù)源}// 1 選中品牌fun selectBrand(brand: String) {selectedBrand.value = brand} }原來狀態(tài)記錄的核心是 LiveData,當(dāng)狀態(tài)方 selectedBrand 發(fā)生變化的時(shí)候,通過擴(kuò)展方法 switchMap 將轉(zhuǎn)化為 Paging 2 中對(duì)應(yīng)的數(shù)據(jù)源 LiveData。
如果是用 Flow 改怎么做呢?
一、冷流還是熱流
在介紹正文之前,我先給大家介紹一下概念,冷流和熱流。
如果之前了解過 Kotlin 的協(xié)程,那么你就有可能知道 Flow 是冷流,什么是冷流?簡(jiǎn)單來說,如果 Flow 有了訂閱者 Collector 以后,發(fā)射出來的值才會(huì)實(shí)實(shí)在在的存在于內(nèi)存之中,這跟懶加載的概念很像。
與之相對(duì)的是熱流,我們即將介紹的 StateFlow和 SharedFlow 是熱流,在垃圾回收之前,都是存在內(nèi)存之中,并且處于活躍狀態(tài)的。
StateFlow
對(duì)于 StateFlow,官方的介紹是:
StateFlow 是一個(gè)狀態(tài)容器式可觀察數(shù)據(jù)流,可以向其收集器發(fā)出當(dāng)前狀態(tài)更新和新狀態(tài)更新。
乍一看,和 Flow 沒什么區(qū)別,但是你看使用代碼,卻是有很大的區(qū)別。
1. StateFlow使用
第一步:創(chuàng)建 MutableStateFlow 并設(shè)置初始化的值。
class MainViewModel : ViewModel() {val selected = MutableStateFlow<Boolean>(false) }第二步:同 Flow 一樣,使用 collect 方法:
lifecycleScope.launch {viewModel.selected.collect {// ... 引起UI發(fā)生的變化// 比如 某個(gè)按鈕是否選中狀態(tài)} }第三步:可以給 selected設(shè)置值,從而引起 Ui 層的變化:
class MainViewModel : ViewModel() {val selected = MutableStateFlow<Boolean>(false)fun doSomeThing(value: Boolean) {selected.value = value} }普通的 Flow,是不具備 selected.value = value 這種能力的。
仔細(xì)觀察一下,這個(gè)使用體驗(yàn)完全跟 LiveData一樣,所以它的使用場(chǎng)景和 LiveData 也很類似。
2. 和LiveData比較
那么 StateFlow 和 LiveData 有什么區(qū)別嗎?
有兩點(diǎn)區(qū)別:
- 第一點(diǎn),StateFlow 必須有初始值,LiveData 不需要。
- 第二點(diǎn),當(dāng) View 變?yōu)?STOPPED 狀態(tài)時(shí),LiveData.observe() 會(huì)自動(dòng)取消注冊(cè)使用方,而從 StateFlow或任何其他數(shù)據(jù)流收集數(shù)據(jù)則不會(huì)取消注冊(cè)使用方。
對(duì)于 StateFlow在界面銷毀的時(shí)仍處于活躍狀態(tài),有兩種解決方法:
- 使用 ktx 將 Flow 轉(zhuǎn)換為 LiveData。
- 在界面銷毀的時(shí)候,手動(dòng)取消(這很容易被遺忘)。
3. 如何解決開頭的問題
關(guān)于開頭的問題,給出的解決方案如下:
class MainViewModel : ViewModel() {private val selectedKind = MutableStateFlow("全部")// 2. 數(shù)據(jù)源根據(jù)selectedBrand自動(dòng)發(fā)生切換val shoes: Flow<Shoe> = selectedKind.flatMapLatest {// ... 切換成對(duì)應(yīng)的數(shù)據(jù)源}// 1. 選中品牌fun selectedBrand(brand: String) {selectedKind.value = brand} }flatMapLatest方法的作用:該方法可以產(chǎn)生一個(gè)新的 Flow,但是只處理最新接收到的值,比如,我先選中 Nike,后選中 Adidas,但是可能因?yàn)檠舆t,兩個(gè)信號(hào)同時(shí)被接收,這個(gè)時(shí)候只會(huì)去請(qǐng)求 Adidas 的數(shù)據(jù)流。
新的結(jié)構(gòu):
由于 StateFlow 是熱流,當(dāng)它擁有一個(gè)初始的值后,在一開始就能通過 flatMapLatest 轉(zhuǎn)換成對(duì)應(yīng)的數(shù)據(jù)源,并且可以通過 selectedBrand 設(shè)置值,動(dòng)態(tài)引起數(shù)據(jù)流 shoes 的變化。
總結(jié)
以上是生活随笔為你收集整理的Android StateFlow详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android SharedFlow详解
- 下一篇: kotlin 协程异常处理机制颠覆三观