# What is a Flow? ## 播放清單介紹與主題 - 本播放清單主題是「Kotlin Flows」。 - 將深入探討Flows的概念、必要性及使用方法。 ## Flow的基本概念  - Flow是一種協程(Coroutine)。 - 與普通協程不同,Flow可以發射(emit)多個值。 - Flow屬於反應式編程,處理隨時間推移的數據序列。 ## Flow的應用情境 - Flow適用於管理UI更新、處理網絡回應及執行異步任務。 - Flow像一個管道,逐步提供所需數據,並在ViewModel或UI中處理這些數據。 ## Flow的工作流程 - **加載狀態**:通知ViewModel正在加載數據,顯示進度條。 - **數據獲取**:獲取數據後通知ViewModel,更新UI顯示內容。 - **數據篩選**:篩選數據後再次通知ViewModel,進行UI更新。 - **結束加載**:返回篩選後的數據列表,隱藏進度條,結束Flow。 # Writing Flow Examples ## 影片介紹與主題 - 這是Kotlin Flows播放清單的第二支影片。 - 影片展示兩個範例:資料獲取與倒數計時器。 ## 第一個範例:資料獲取的Flow  - **函數定義**:建立返回Flow的函數,該Flow會發射多個字符串值。 - **流程步驟**:  - 發射 "start loading" 表示開始加載資料。 - 延遲1秒,模擬資料獲取過程,發射 "got data"。 - 發射 "start filtering data" 表示開始篩選資料。 - 發射 "data is ready" 表示資料準備完成。 - 最後發射 "stop loading" 表示結束加載。 ## 資料收集與處理  - 使用 `flow.collect` 收集Flow中的資料。 - 打印接收到的資料,以便查看流程執行情況。 ## 第二個範例:倒數計時器Flow  - **計時器設置**:初始時間設置為10秒,每秒發射當前時間值。 - **流程步驟**: - 每次發射後時間減少1秒,直到時間減少至零。 - 發射過程中避免發射負值,當時間為0時停止。 ## 倒數計時器的資料收集 - 在UI中顯示每次發射的時間值,從10秒倒數到0。 # Operators: FlatMapLatest - Concat - Filter - Map ## 影片介紹與主題 - 本影片是Kotlin Flows播放清單的第三支影片。 - 介紹四個常用的Flow操作符:`filter`、`map`、`flatMapLatest`、`flatMapConcat`。 ## 建立Flow範例  - 建立一個名為 `flow` 的函數,返回一個 `Flow<String>`。 - 使用計數器並發射多個不同的字符串值。 ## `filter` 操作符  - **用途**:過濾掉不符合條件的發射值。 - **範例**:只保留包含 "this" 的發射值,忽略包含 "that" 的發射值。 ## `map` 操作符   - **用途**:將發射值轉換為另一個值。 - **範例**:將每個符合條件的發射值轉換為 "new" 或進行數值運算。 ## `flatMapConcat` 操作符  - **用途**:將一個Flow的發射值轉換為另一個Flow,並順序處理每個發射值。 - **範例**:對每個發射值乘以10,並順序發射轉換後的結果。 ## `flatMapLatest` 操作符  - **用途**:只處理最新的發射值,忽略先前的發射值。 - **範例**:在處理新發射值時,取消處理舊發射值,只保留最後一個結果。 ## 操作符比較 - **`flatMapConcat`**:依次處理每個發射值,等待每個Flow的完成。 - **`flatMapLatest`**:僅處理最新的發射值,忽略中間過程中的其他發射值。 # CollectLatest ## 影片介紹與主題 - 本影片是Kotlin Flows播放清單的第四支影片。 - 本影片介紹`collectLatest`操作符的使用,並透過範例說明其應用。 ## 範例設置:模擬搜尋功能 - **結果列表**:建立一個包含多個程式語言文件的字串列表,包括Kotlin、Java和Swift。 - **搜尋函數**:建立一個返回 `Flow<String>` 的函數,模擬使用者輸入搜尋查詢時所返回的結果。  ## `collectLatest` 的用途 - **問題描述**:使用者可能會快速變更搜尋查詢,並希望只獲取最新的搜尋結果,而不是所有中間結果。 - **解決方案**:使用`collectLatest`,只收集並處理最新的發射值,忽略先前的發射值。 ## `collectLatest` 的實作 - **未使用`collectLatest`的情況**:當使用者輸入多個查詢時,會返回所有匹配的結果,例如Kotlin、Java和Swift的文件。 - **使用`collectLatest`的情況**:當使用者輸入多個查詢時,只返回最終查詢的結果,例如只返回Swift的文件。 ## 範例執行結果 - 當使用`collectLatest`時,僅顯示使用者最終查詢的結果,忽略中途的其他結果。   # State Flow ## State Flow 簡介 - State Flow 類似於普通的 Flow,但它不會隨時間發送多個值,而是只保存一個狀態。 - State Flow 用來保存 UI 狀態或活動狀態,避免在配置變更(例如螢幕旋轉)時丟失狀態。 - State Flow 類似於 LiveData,但不具備生命週期感知,並且使用協程,這是其優勢。 ## 創建 State Flow  - 使用 `MutableStateFlow` 創建一個可變的狀態流,並給它一個初始值。 - 創建一個不可變的公有狀態流,使用 `asStateFlow` 將可變狀態流轉換為不可變。 - 創建一個函數來更新狀態,並在 UI 中觀察該狀態的變化。 ## 在 Compose 中使用 State Flow - 在 `ViewModel` 中創建狀態流並更新它。 - 在 `Composable` 函數中使用 `collectAsState` 來收集狀態流的值並顯示在 UI 中。 - 當使用者在 TextField 中輸入內容時,更新狀態流中的文字並及時顯示。 ## 在 XML 中使用 State Flow   - 在非 Compose 專案中(例如使用 XML 的專案),可以使用 `lifecycleScope.launch` 和 `repeatOnLifecycle` 來收集狀態流的值。 - 使用 `collectLatest` 來顯示最新的狀態值在 UI 中,避免顯示舊值。 ## 其他重點 - State Flow 相較於 LiveData 的優勢在於可以使用 Flow 操作符如 `map`、`filter` 等。 # Shared Flow - Channels ## Shared Flow 與 Channel 簡介  - 在前一個視頻中介紹了 State Flow,用於在配置變更(例如螢幕旋轉)時保持狀態。 - 本視頻介紹 Shared Flow 和 Channel,它們都用於發送一次性事件,例如顯示 Toast、Snackbar、Alert Dialog 或進行導航。 - Shared Flow 和 Channel 的主要用途是在特定事件發生時通知 UI,例如驗證成功後通知 UI 進行導航。 ## Shared Flow 與 Channel 的特性 - Shared Flow 是熱流(Hot Flow),它會在沒有收集器的情況下繼續發送事件,這可能導致事件丟失。 - Channel 是冷流(Cold Flow),它不會在沒有收集器的情況下發送事件,因此不會丟失事件。 ## 在 ViewModel 中使用 Shared Flow 和 Channel - 在 `ViewModel` 中初始化 Shared Flow 和 Channel,並在特定情況下發送事件(例如在用戶驗證成功後顯示 Toast)。 - 使用 `ViewModelScope.launch` 來啟動協程,發送事件給 Shared Flow 或 Channel。 ## 在 Compose 中收集 Shared Flow 和 Channel 的事件 - 使用 `LaunchedEffect` 在 Compose 中收集事件,確保事件只觸發一次。 - 使用 `collect` 或 `collectLatest` 來收集事件並更新 UI。 ## Shared Flow 與 Channel 的比較範例 - 如果使用 Shared Flow,當活動處於背景或沒有收集器時,Shared Flow 仍然會發送事件,這些事件可能會丟失。  - 如果使用 Channel,在沒有收集器時不會發送事件,事件不會丟失。 - 跳去別的 Activity 回來資料也不會丟失。   ## 實際應用中的考量 - 如果事件對用戶來說非常重要,例如顯示 Toast、Snackbar 等,應使用 Channel,因為它不會丟失事件。 - Shared Flow 可以有多個收集器,非常適合多個部分需要同時接收通知的情況,例如當用戶身份驗證過期時通知應用的不同部分。 - Channel 僅能有一個收集器,適合單一用途的情境,例如顯示單一的 Toast。 ## 結論 | 特性 | Shared Flow | Channel | |---------------|-------------------------------|---------------------------------| | 類型 | 熱流 (Hot Flow) | 冷流 (Cold Flow) | | 是否需要收集器 | 不需要 | 需要 | | 事件丟失 | 可能會丟失 | 不會丟失 | | 多重收集器支持 | 支援 | 不支援 | | 使用場景 | 多個部分需同步更新 | 單一用途,如顯示 Toast | | 實際應用 | 用戶身份驗證過期,通知應用的多個部分 | 顯示 Toast 或 Snackbar,避免事件丟失 | | 比較範例 | 在應用程式啟動時開始發送事件,即使沒有收集器,這可能導致事件丟失 | 僅在有收集器時才開始發送事件,確保所有事件都被處理 | - Shared Flow 適合需要多個收集器的情況,如應用內多個部分需要同步更新。 - Channel 更適合單一收集器的情況,如顯示 Toast 或 Snackbar,確保不丟失任何重要事件。 # Terminology - **Flow**:Kotlin 協程中的資料流,允許發射多個值並觀察這些值隨時間的變化。 - **Coroutine**:Kotlin 的輕量級非阻塞式線程,用於處理異步任務。 - **Reactive Programming**:處理非同步資料流的編程範式,允許系統自動對資料變化做出反應。 - **Emit**:在 Flow 中發射值到流中,使觀察者能夠接收到這些值。 - **ViewModel**:Android 架構組件,用於管理 UI 資料,確保資料在配置變更時不會丟失。 - **UI(User Interface)**:用戶界面,與使用者互動的視覺元素集合。 - **API(Application Programming Interface)**:應用程式介面,允許不同系統之間的互動和資料交換。 - **Database**:資料庫,存儲和管理應用程式所需的資料。 - **Filter**:處理資料的一個步驟,用來篩選出符合條件的資料並去除不需要的部分。 - **Flow**:Kotlin 協程中的資料流,可以隨時間發射多個值並讓觀察者接收這些值。 - **Emit**:在 Flow 中發射值,使觀察者能夠接收到這些值並作出相應處理。 - **Delay**:Kotlin 協程中的一個函數,允許暫停協程執行一段時間,通常用於模擬網絡延遲或計時器。 - **Coroutine**:Kotlin 中的輕量級線程,允許非同步程式的執行而不阻塞主線程。 - **RunBlocking**:Kotlin 協程中的一個函數,用於啟動協程並阻塞主線程直到協程完成,通常用於測試或範例程式碼中。 - **Collect**:Flow 的終端操作符,用於收集流中的數據,並在每次發射值時執行相應的邏輯。 - **Log**:Android 中用於輸出日誌訊息的工具,通常用於調試和監控應用程式的行為。 - **Countdown Timer**:倒計時器,一種應用場景,用於隨時間遞減並發射剩餘的秒數,直到倒計時結束。 - **Collect Latest**:Flow 的一種操作符,用於只收集最新發射的值,並取消對之前值的收集。 - **Flow Operators**:用於轉換、過濾或合併 Flow 中的數據,例如 `filter`、`map`、`flatMapConcat`、`flatMapLatest` 等操作符。 - **Filter**:一種 Flow 操作符,用於篩選符合特定條件的數據,只保留返回 true 的數據。 - **Map**:一種 Flow 操作符,用於將流中的每個元素轉換為另一個值,生成新的流。 - **FlatMapConcat**:一種 Flow 操作符,用於將流中的每個元素映射為另一個 Flow,並按順序依次發射每個 Flow 的元素。 - **FlatMapLatest**:一種 Flow 操作符,類似於 `FlatMapConcat`,但只保留和發射最後一個映射的 Flow 中的元素,並取消之前的 Flow。 - **RunBlocking**:Kotlin 協程中的一個函數,用於啟動協程並阻塞主線程直到協程完成。 - **Delay**:Kotlin 協程中的一個函數,用於暫停協程執行一段時間,通常用於模擬時間延遲。 - **Collect**:Flow 的終端操作符,用於啟動流並收集流中的數據。 - **Log**:Android 中用於輸出日誌訊息的工具,通常用於調試和監控應用程式的行為。 - **collectLatest**:一種Kotlin中的流操作符,用來收集最新的數據,當新數據發射時,如果前一個數據的處理尚未完成,會自動取消前一個數據的處理並處理最新的數據。 - **flow**:Kotlin中的一種冷流(Cold Stream),可以用來異步地發射一系列數據,類似於RxJava中的Observable。 - **runBlocking**:一種用來啟動協程的函數,在該函數內部的所有協程會阻塞當前線程直到所有的協程執行完畢。 - **delay**:一種用來暫停協程一段時間的非阻塞函數,常用於模擬異步操作。 - **emit**:一種用來在Flow中發射數據的函數。 - **log**:一種用來記錄日誌的函數,用於調試或監控程序執行狀況。 - **mutable shared flow**:一種特殊的Kotlin流,用於在多個消費者之間共享數據,可以用來實現類似於事件總線的功能。 - **state flow**:Kotlin中的一種特殊流,保存並發射最新的狀態值,類似於LiveData。 - **shared flow**:一種熱流(Hot Stream),可在多個消費者間共享數據,適用於事件流的情境。 - **StateFlow**:一種Kotlin中的特殊流,類似於普通的Flow,但它只保持一個狀態值。當狀態值變化時,它會通知觀察者更新UI,通常用來保存UI或活動狀態,以避免在配置更改(如旋轉屏幕)時丟失這些狀態。 - **MutableStateFlow**:StateFlow的一個可變版本,可以在ViewModel中使用來保存和更新狀態值,並將其公開為不可變的StateFlow供UI觀察。 - **LiveData**:一種Android架構組件,專為UI設計的可觀察數據容器,具有生命週期感知功能。與StateFlow不同的是,StateFlow沒有生命週期感知能力。 - **collectAsState**:一種在Jetpack Compose中收集StateFlow狀態並將其轉換為可觀察狀態的函數,用於在Compose中觀察StateFlow的變化。 - **LifecycleScope**:與活動或Fragment的生命週期關聯的協程範圍,用於在生命週期內啟動協程。 - **repeatOnLifecycle**:一個用於在指定的生命週期狀態下反覆執行的函數,通常與LifecycleScope一起使用來收集Flow或StateFlow的數據。 - **viewModelScope**:專為ViewModel設計的協程範圍,確保協程在ViewModel被清除時自動取消。 - **setContent**:Jetpack Compose中設置活動UI的函數,使用Compose語法定義UI結構。 - **collectLatest**:Kotlin中的流操作符,確保只處理最新發射的數據,如果在新數據發射之前正在處理舊數據,則會取消舊數據的處理。 - **update**:一個用於更新MutableStateFlow狀態值的函數,確保狀態變化後觸發觀察者的更新。 - **SharedFlow**:一種Kotlin的熱流(Hot Flow),它可以發送一次性事件。SharedFlow可以有多個收集器,適合用來通知應用中多個部分某些狀態變更,如用戶身份驗證失敗或成功。由於SharedFlow是熱流,即使沒有收集器,它也會持續發送事件,如果沒有及時收集,事件可能會丟失。 - **Channel**:Kotlin中的一種冷流(Cold Flow),用於發送一次性事件。與SharedFlow不同,Channel只有在有收集器時才會發送事件,因此不會丟失事件。但Channel僅支持單一收集器,適合用於顯示Toast、Snackbar等單一UI操作。 - **冷流(Cold Flow)**:只有在有收集器時才會開始發送數據的流,如Channel。 - **熱流(Hot Flow)**:不需要收集器也會持續發送數據的流,如SharedFlow。 - **collect**:Kotlin流中的一個操作符,用來收集並處理流中發送的所有數據。與`collectLatest`不同,`collect`會處理每一個發送的數據,而不會丟棄未處理的數據。 - **collectLatest**:一種Kotlin流操作符,用來只處理最新發送的數據。如果新的數據來了而之前的數據還沒處理完成,則會取消之前的處理。 - **viewModelScope**:與ViewModel的生命週期相關聯的協程範圍,適合用來啟動與UI相關的操作。 - **delay**:Kotlin中的一個函數,用來在協程中非阻塞地暫停執行一段時間,常用於模擬異步操作。 - **launch**:Kotlin中的一個函數,用來啟動一個新的協程。 - **init block**:Kotlin中的初始化區塊,當一個類的實例被創建時,init區塊內的代碼會首先被執行,用於初始化類中的變量或執行其他初始化邏輯。 - **LifecycleScope**:與Activity或Fragment的生命週期相關聯的協程範圍,確保協程在Activity或Fragment的生命週期結束時自動取消,常用於在生命週期內執行異步任務。 - **Main dispatcher**:Kotlin協程中的一個調度器,用來將協程分派到主線程上執行,適合用於與UI相關的操作。 - **`launchIn`**:一個擴展函數,用來在指定的協程範圍內啟動並收集流,它可以使流在指定的協程範圍內持續運行。 - **Hot vs Cold Flow**:熱流(Hot Flow)會不斷發送數據,即使沒有收集器。而冷流(Cold Flow)僅在有收集器時才會開始發送數據。 - **StateFlow vs SharedFlow**:StateFlow用於保存狀態(如UI狀態)並在狀態變更時通知觀察者,適合用於管理持續狀態。SharedFlow則用於發送一次性事件,如通知某些操作已經完成或觸發某些操作。 - **LaunchedEffect**:在Jetpack Compose中,一種啟動和管理協程的組件,適合用來在組件的特定生命週期階段啟動協程,並確保在組件重組期間協程不會重啟。 - **Composable**:Jetpack Compose中的基本構建塊,標註為`@Composable`的函數可以描述UI,並允許使用聲明式的方式構建用戶界面。 - **MutableSharedFlow**:SharedFlow的一個可變版本,允許在SharedFlow中發送事件,適合用於場景中需要多次更新或發送事件的情況。 - **startActivity**:Android中的一個方法,用來啟動新的Activity,通常與`Intent`一起使用來傳遞數據或設定啟動目標。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up