關(guān)于Android Flow

本篇文章默認(rèn)會相關(guān)協(xié)程基礎(chǔ)...

什么是Flow?

我們可以簡單理解為Flow是Android協(xié)程庫中的一套對數(shù)據(jù)流處理的API,Flow以協(xié)程為基礎(chǔ)構(gòu)建,可以按順序發(fā)出多個(gè)值。

它關(guān)注的是數(shù)據(jù)流是否有背壓的問題,是否有消費(fèi)不平衡的問題.

背壓:簡單理解就是生產(chǎn)太多消費(fèi)不了(飯做多了吃不下了)

數(shù)據(jù)流包含三個(gè)實(shí)體(官方圖1):

1.提供方:生成添加到數(shù)據(jù)流中的數(shù)據(jù)。

2.(可選)中介:可以修改發(fā)送到數(shù)據(jù)流的值,或者修正數(shù)據(jù)流本身

3.消費(fèi)方:消費(fèi)數(shù)據(jù)流中的值.

官方對Flow的定義:Flow結(jié)合協(xié)程可以代替RxJava在Android中的地位.

從官方定義中我們也可以看出有了協(xié)程和Flow我們是可以完全代替RxJava.


為什么已經(jīng)有了RxJavaGoogle還要搞一套協(xié)程和Flow呢?

1.RxJava源碼晦澀難懂、操作符眾多,學(xué)習(xí)成本高.

2.RxJava是第三方庫.


Flow基本使用(圖2):

圖2

此時(shí)我們運(yùn)行程序會發(fā)現(xiàn),在控制臺hello方法并沒有打印任何東西!說明程序并沒有進(jìn)入到hello方法中,這是為什么呢?

這就不得不引申出一個(gè)詞‘冷流’!,這是因?yàn)镕low是‘冷流’.

那么‘冷流’是什么意思呢?

冷流:就是在數(shù)據(jù)被訂閱或者說要被消費(fèi)的時(shí)候,發(fā)布者才開始執(zhí)行發(fā)射數(shù)據(jù)流的代碼,如果有多個(gè)訂閱者,每一個(gè)訂閱者和發(fā)布者都是一對一的關(guān)系,相當(dāng)于每個(gè)訂閱者都會收到發(fā)布者的完整數(shù)據(jù)。

假設(shè)我們要從數(shù)據(jù)庫中獲取3條數(shù)據(jù),使用Flow則不需要等到3條數(shù)據(jù)全部取出來之后再更新,而是可以實(shí)時(shí)的接受數(shù)據(jù)更新(圖3)。

圖3

再次運(yùn)行程序,輸出結(jié)果(圖4):

圖4

從圖4中可以看出,作用域下的hello使用了collect訂閱Flow(Flow是一個(gè)掛起函數(shù))之后,程序進(jìn)入了hello方法,并且接收到發(fā)送過來的一個(gè)個(gè)數(shù)值。

Flow還為我們提供了很多操作符:

flowOn操作符:如果需要將Flow中的代碼塊進(jìn)行線程切換,可以使用flowOn操作符。

如果我們直接在hello方法中加個(gè)協(xié)程進(jìn)去線程切換(圖5),會發(fā)現(xiàn)程序崩潰拋出了異常(圖6)。這是為什么呢?

因?yàn)樘峁┓讲荒芴峁﹣碜圆煌珻oroutineContext的emit值,所以不能再Flow中創(chuàng)建協(xié)程作用域并發(fā)送結(jié)果。

而錯(cuò)誤日志也已經(jīng)提示我們(please refer to 'flow' documentation or use 'flowOn' instead.)要用flowOn進(jìn)行切換。

圖5
圖6

正確的寫法(圖7):

圖7

filter操作符:可以對結(jié)果添加限制的功能.

比如我只想獲取值等于2的結(jié)果圖8:

圖8

運(yùn)行程序輸出的結(jié)果(圖9):

圖9

除了冷流還有對應(yīng)的熱流:

flow{}創(chuàng)建的數(shù)據(jù)流默認(rèn)是冷流,那么他們兩者有什么區(qū)別呢?

熱流(SharedFlow和StateFlow):不管是否被訂閱或者消費(fèi),都會執(zhí)行發(fā)射數(shù)據(jù)流的操作,并且發(fā)布者和訂閱者是一對多的關(guān)系.


SharedFlow?和?StateFlow都是熱流。即沒有觀察者,數(shù)據(jù)會持續(xù)更新,與LiveData類似。 其中MutableSharedFlow與MutableStateFlow是它們的可變類型。

StateFlow的使用場景和LiveData是非常相似的,下面以ViewModel中改變數(shù)值變化為例進(jìn)行演示(圖10):

圖10

上述代碼在ViewModel輸入文字的前面添加了Test字符串,并將監(jiān)聽結(jié)果返回展示在UI中。而MutableStateFlow是StateFlow的可變類型,可以看見和LiveData組件不同的是,這里的MutableStateFlow必須指定默認(rèn)值,在MainActivity中調(diào)用textChange方法監(jiān)聽結(jié)果(圖11):

圖11

運(yùn)行程序輸入‘123’,多次點(diǎn)擊提交你會發(fā)現(xiàn),如果值沒有改變,StateFlow是不會回調(diào)collect函數(shù)。只會會顯示你第一次提交的值,并且StateFlow總會先收到默認(rèn)值。


還有一些常用的操作符:

asFlow:將其他數(shù)據(jù)轉(zhuǎn)換成Flow,一般都是集合向Flow的轉(zhuǎn)換,如listOf(1,2,3).asFlow().

flowof:構(gòu)造一組數(shù)據(jù)的Flow進(jìn)行發(fā)送.

map:對上游發(fā)送的數(shù)據(jù)進(jìn)行變換,collect最后接收的是變換之后的值.

mapNotNull:僅發(fā)送map之后不為空的值.

mapLatest:類似于collectLatest,當(dāng)emit發(fā)射新值,則會取消掉map上一次轉(zhuǎn)換還未完成的值.

filterNot:與filter相反,篩選不符合條件的值,返回false繼續(xù)往下執(zhí)行.

filterNotNull:篩選不為空的值.

drop:drop(count: Int)參數(shù)為Int類型,意為丟棄掉前count個(gè)值.

dropWhile:找到第一個(gè)不滿足條件的值,返回其和其后所有的值.

take:與drop()相反,意為取前n個(gè)值.

還有一些操作符等等...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容