什麼是冷資料流#
Flow 的一個重要特性是它屬於 冷資料流(Cold Stream):在沒有人呼叫 collect 之前,flow 內部的程式碼不會被執行。
換句話說:
- 建立 Flow 只是「定義」資料如何被產生。
- 呼叫
collect才會真正啟動產生資料的流程。 - 每呼叫一次
collect,flow 內的程式碼就會重新執行一次。
這個性質與「熱資料流」(Hot Stream)對比:熱資料流會主動發送資料,不論有沒有訂閱者;冷資料流則只在被訂閱時才執行。
Cold Stream 範例#
延續前一篇的 flow1:
fun flow1(): Flow<Int> = flow {
println("Flow started")
repeat(10) {
delay(100)
emit(it)
}
}如果 collect 兩次:
fun main() = runBlocking {
val flow = flow1()
flow.collect { value -> println(value) }
flow.collect { value -> println(value) }
}執行結果:
Flow started
0
1
2
3
4
5
6
7
8
9
Flow started
0
1
2
3
4
5
6
7
8
9可以看到 Flow started 被印了兩次,0 ~ 9 也跑了兩遍。這證明:
- 同一個 Flow 物件可以被多次 collect。
- 每一次 collect,都會從頭跑一次 flow 內的程式碼。
為什麼這個性質重要#
冷資料流帶來幾個好處:
- 「定義」與「執行」解耦:可以先把資料來源寫好放著,要用的時候才觸發。
- 多次訂閱可以拿到一致的資料序列,不用擔心「之前的資料已經跑掉了」。
- 中間運算子(map、filter 等)可以放心地疊在冷流之上,因為整條鏈路會在 collect 時統一觸發。
反過來說,如果需要的是「不論誰訂閱、資料都持續流動」的場景,例如點擊事件、感測器資料,就需要 SharedFlow / StateFlow 這類「熱資料流」工具。
小結#
- Flow 是冷資料流:沒有
collect,內部就不執行。 - 每次 collect 都會重新執行 flow 內的程式碼,得到全新的一條流。
- 建立 Flow 的函式不需要是 suspend,因為它只是宣告。
- 真正會 suspend 的是 collect 端。
原文出處#
- 原書/iThome:https://ithelp.ithome.com.tw/articles/10269815