社區(qū)說|Kotlin Flow 的原理與設計哲學

Kotlin Flow 的原理與設計哲學
一、基本用法

Flow:流,有上游和下游,上游發(fā)射數(shù)據(jù)、下游接收數(shù)據(jù)

上游:Flow
下游:FlowCollector

設計的巧妙之處:Flow 有collect(收集)的能力,F(xiàn)lowCollector 有 emit(發(fā)射)的能力

Flow的collect 函數(shù)其實在發(fā)射數(shù)據(jù),F(xiàn)lowCollector的 emit 函數(shù)其實是在接收數(shù)據(jù),使用時省略了emit函數(shù)聲明。

二、“冷”數(shù)據(jù)流背后的原理
冷數(shù)據(jù)流的含義:無收集者時不發(fā)射數(shù)據(jù)。無下游時上游不發(fā)數(shù)據(jù)。

冷數(shù)據(jù)流的另一特征:懶
執(zhí)行順序如注釋所示:一次 emit 對應一次 collect。
只有當數(shù)據(jù)被需要時,才會被觸發(fā)發(fā)射數(shù)據(jù)操作。便于開發(fā)者寫出高效代碼

Flow在源碼中的體現(xiàn):
1、執(zhí)行Flow 的 collect 函數(shù):

2、執(zhí)行SafeFlow 的collectSafely 函數(shù):

3、執(zhí)行 SafeCollector的 block 表達式。該 block 表達式即為開發(fā)者定義的 flow 函數(shù)的參數(shù):

4、執(zhí)行 Flow 的 collect 函數(shù):

5、執(zhí)行 FlowCollector 的 emit 函數(shù),通知上游發(fā)數(shù)據(jù):


6、啟動協(xié)程,執(zhí)行私有函數(shù) emit :

7、執(zhí)行 emitFun 函數(shù)并返回:

8、代碼調(diào)用到開發(fā)者定義的 FlowCollector的emit 函數(shù),接收數(shù)據(jù):

Flow 的 collect 函數(shù)和FlowCollector 的 emit 函數(shù)都是提供給對方調(diào)用的。
總結(jié)1:“冷”數(shù)據(jù)流
Flow的架構(gòu)模型

三、Flow中間操作符用法
中間操作符:filter、map、take

在一次 emit 中,中間操作符的執(zhí)行過程與代碼一一對應:

四、Flow的攜程作用域細節(jié)
可以在協(xié)程作用域外創(chuàng)建 Flow,在協(xié)程內(nèi)收集時執(zhí)行:

創(chuàng)建 flow 的函數(shù)不是一個掛起函數(shù)。在創(chuàng)建數(shù)據(jù)和中間操作的過程中無需協(xié)程作用域,在下游收集處需要協(xié)程作用域:

總結(jié)2:最小化協(xié)程依賴

五、源碼背后的數(shù)據(jù)流串聯(lián)思想
Flow 操作符源碼:
以 filter 為例,內(nèi)部函數(shù)調(diào)用的返回值始終是 Flow。執(zhí)行順序如注釋所示:

map操作符,在emit前進行一次轉(zhuǎn)換:

總結(jié)3:數(shù)據(jù)流串聯(lián)。
通過一層一層的包裝,實現(xiàn)串聯(lián)的模型。
從下到上一層一層觸發(fā),從上到下一層一層轉(zhuǎn)換:

總結(jié)
Flow的設計哲學
- “冷”數(shù)據(jù)流:冷、懶
- 最小化協(xié)程依賴:結(jié)構(gòu)化并發(fā)、上下文保護
- 結(jié)構(gòu)化并發(fā):父子協(xié)程、生命周期聯(lián)動
- 上下文聯(lián)動:每次emit 時的上下文不可變更
- 數(shù)據(jù)流串聯(lián)
問答互動
1、SharedFlow 和 StateFlow的應用場景?
StateFlow 用來替代 LiveData,可以使用 flow 的操作符,ui 層無需處理;SharedFlow 用在多個接收者場景
2、 為什么說 Flow 天然支持背壓?
上一個 emit 函數(shù)沒有執(zhí)行完時,下一個 emit 函數(shù)無法執(zhí)行
3、閱讀Flow源碼的推薦順序?
1、首先要熟悉 kotlin 的高階函數(shù)
2、然后要熟悉協(xié)程的基礎概念
3、再去看 flow 的源碼,了解實現(xiàn)原理