本篇文章默認(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):

此時(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)。

再次運(yùn)行程序,輸出結(jié)果(圖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)行切換。


正確的寫法(圖7):

filter操作符:可以對結(jié)果添加限制的功能.
比如我只想獲取值等于2的結(jié)果圖8:

運(yùn)行程序輸出的結(jié)果(圖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):

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