Try   HackMD

Full Guide to Jetpack Compose Effect Handlers

Side‑Effect 定義與問題

  • 在 Compose 中,任何「逃離 Composable 函式範疇」的動作皆屬副作用,如存取全域變數或發送網路請求。
  • 副作用若直接寫在 Composable 內,重組次數與時機不可控,會造成重複執行、狀態錯亂或性能浪費。
  • 透過效果處理器(Effect Handlers)將副作用封裝,可明確控制生命週期並降低不可預期行為。若仍堅持將副作用留在 UI 層,即使理解理論也難避免隱性錯誤。

LaunchedEffect

  • 以 Composable 形式存在,會在組成時啟動 coroutine,可安全呼叫 suspend 函式。
  • 接收 key 參數:key 變動時先取消現行 coroutine,再以新值重新啟動;傳入 true 可保證只執行一次。
  • 適用場景:一次性收集 Flow、進行動畫、啟動背景作業等。
  • 取消與重新啟動由 Compose 管理,不需手動追蹤;忽略 key 機制等於放棄針對重組的精準控制。

rememberCoroutineScope

  • 於 Composable 中產生與組成生命週期綁定的 CoroutineScope,離開組成時自動取消。
  • 僅用於回呼(如 onClick、onTextChange)啟動 coroutine;若放在 Compose 主體區塊仍會造成副作用重組問題。
  • 在成熟架構中多數協程可交由 ViewModel 的 viewModelScope 處理,直接依賴 UI Scope 反而增高耦合度,除非確有需要啟動短生命週期協程才使用。

rememberUpdatedState

  • 解決協程或 callback 捕獲過時參數的問題,保留狀態的最新引用而不觸發重新執行。
  • 常見案例:Splash 畫面倒數、計時器、動畫等僅需執行一次卻可能接收新版 lambda 的情境。
  • 將最新值包裝於 rememberUpdatedState 後傳入協程,可避免因 UI State 變動而延長或重啟作業;若忽視此作法,容易導致行為與預期不符。

DisposableEffect

  • 適合在 Composable 內註冊需要「清除」的監聽器或資源,例如 LifecycleObserver。
  • 接收 key;當 key 變動時先執行 onDispose 清理,再重新建立資源。
  • onDispose 於 Composable 移出組成時觸發,確保移除觀察者、關閉連線、釋放記憶體。
  • 重組期間不會重複建立監聽器,避免資源洩漏與重複回呼。

SideEffect

  • 於每次成功重組後執行,用來同步非 Compose 控制的外部狀態。
  • 無 key;只負責在重組完成後寫入或更新外部物件,如記錄分析事件或設定第三方 SDK 值。
  • 不適合執行耗時作業或需要清理的行為,只做快速同步。

produceState

  • 在 Composable 內建立 coroutine 產生「隨時間變化」的 State。
  • 以 initialValue 為起始,透過 coroutineScope 持續修改 value ,Compose 自動重新繪製。
  • 可替代 Flow + collectAsState,將非同步結果直接轉成可觀察狀態。
  • 與 Composable 生命週期綁定,離開組成時協程自動取消。

derivedStateOf

  • 建立「依賴多個 State 計算得來」且可能昂貴的衍生值,具備快取與自動更新。
  • 當依賴的 State 改變時才重新計算;其餘讀取皆回傳快取結果,減少重複運算。
  • 適用於複雜字串拼接、清單過濾、昂貴資料轉換等場景。
  • 避免在每次 recomposition 時進行重計算,提升效能。

snapshotFlow

  • 將 Compose State 轉換為 Flow,當 State 改變時發射新值。
  • 支援 Flow operators(debounce、map、distinctUntilChanged 等)以進行反應式處理。
  • 常用於需要觀察 UI 狀態並與非 Compose 層(例如資料層、Analytics)互動的情況。
  • Flow 的生命週期由 collect 方負責;搭配 LaunchedEffect 或 ViewModelScope 可安全收集。

音樂 App

LaunchedEffect

Composable 內啟動一段與 UI 生命週期綁定的 Coroutine。只有依賴值改變時才會重新啟動,離開 Composition 時自動取消。


當使用者切換到不同播放清單 playlistId 時,使用

LaunchedEffect(playlistId) { loadPlaylistTracks(playlistId) }

確保僅在 ID 改變時才重新向伺服器抓取曲目,避免多餘請求;若使用者迅速返回上一清單,協程亦會被取消,節省流量與電量。


rememberCoroutineScope

在 Composable 中記住一個可用於啟動長生命週期工作的 CoroutineScope;Scope 會隨組件離開 Composition 一併取消。


「下載專輯」按鈕需要背景下載多首歌曲並持續顯示進度:

val scope = rememberCoroutineScope()
Button(onClick = {
    scope.launch { downloadAlbum(albumId) }
}) { /* … */ }

可避免因連點造成多支協程同時下載;Component 消失時自動終止未完成下載,防止殘留任務。


rememberUpdatedState

將最新的 value 封裝進 State<T>,讓仍在執行的協程或回呼存取到最新值,而不需重新重組。常用於 LaunchedEffect 內部或回呼引用。


播放進度通知使用者偏好語言:

val currentLocale by rememberUpdatedState(appLocale)
LaunchedEffect(mediaPlayer) {
    mediaPlayer.setOnProgressListener { pos ->
        toast(formatTime(pos, currentLocale)) // 始終拿到最新 locale
    }
}

避免語系變更後仍顯示舊語言時間格式。


DisposableEffect

在進入 Composition 時執行初始化,並在離開時執行清理邏輯。適合與系統 listener、廣播或第三方 API 綁定/解除。


註冊並釋放耳機插拔廣播:

DisposableEffect(Unit) {
    val receiver = HeadsetBroadcast { paused -> if (paused) pause() }
    context.registerReceiver(receiver, intentFilter)
    onDispose { context.unregisterReceiver(receiver) }
}

確保畫面關閉或組件銷毀時不遺留 Receiver,避免記憶體滲漏。


SideEffect

在每次成功重組後執行一次同步函式;不屬於協程,主要用於與外部物件保持一致(例如測量、日誌)。


將目前可見曲目 ID 同步到原生 Android Window 標題(供多工檢視顯示):

SideEffect { activity.title = currentTrack.title }

重組時若 currentTrack 變化,Window 標題即時更新,而不需額外 listener。


produceState

在 Composable 內以協程「產生」一個 State<T>,允許持續發射新值;生命週期同 Composition。


持續讀取播放器緩衝百分比並以 State 回推 UI:

val bufferPct by produceState(0f, mediaPlayer) {
    while (true) {
        value = mediaPlayer.bufferedPercentage
        delay(500)
    }
}
LinearProgressIndicator(progress = bufferPct / 100f)

玩家重啟或畫面離開時,協程自動取消,不會繼續輪詢。


derivedStateOf

根據一組 State 來源,計算出另一個只在來源變動且計算結果改變時才重組的衍生狀態;避免昂貴計算重複執行。


根據播放清單曲目與當前排序模式計算顯示列表:

val sortedTracks by remember(sortMode, tracks) {
    derivedStateOf { sortTracks(tracks, sortMode) }
}
LazyColumn { items(sortedTracks) { TrackRow(it) } }

tracks 未改變時改動 UI 排序不會重新下載封面,提升效能。


snapshotFlow

將連續的 Compose State 讀取封裝為 Cold Flow,每次 snapshot 變動時發出新值,用於橋接 Compose 與非 Compose 協程 API。


監聽音量滑桿並節流寫入偏好:

LaunchedEffect(Unit) {
    snapshotFlow { volumeSliderPosition }
        .debounce(300)
        .collect { setPreferredVolume(it) }
}

Compose Slider 變化頻繁,但只在使用者停止拖動 300 ms 後才寫入,避免 I/O 風暴。


這些 API 多用於處理副作用與狀態同步。若只在 Recomposition 裡做純運算,可考慮避免不必要的協程或 Effect,以減少複雜度與潛在資源浪費。

選擇題

  1. 在 Jetpack Compose 中,何謂「副作用」(side effect)?
    A. 只在預覽模式下執行的程式碼
    B. 超出 Composable 函式範圍、影響外部狀態或資源的操作
    C. 造成版面配置錯亂的 UI 變動
    D. 任何耗費 CPU 的運算
    答案:B

  2. 為何不應該直接在 Composable 函式主體內呼叫網路 API?
    A. Composable 無法存取網路
    B. 可能造成 UI thread 崩潰
    C. 每次重組(recomposition)都會再次執行呼叫,難以控制次數
    D. 會違反 Android 6.0 之後的權限規範
    答案:C

  3. LaunchedEffect 能夠執行 suspend 函式的主要原因是什麼?
    A. 其內部隱含了一個 CoroutineScope
    B. 編譯器會把 suspend 函式改寫成同步
    C. Compose runtime 會自動暫停主執行緒
    D. LaunchedEffect 預設使用 ThreadPoolExecutor
    答案:A

  4. 當傳入 LaunchedEffect 的 key 參數改變時,系統會如何處理?
    A. 忽略新值,維持舊協程
    B. 取消舊協程並重新啟動區塊
    C. 立即關閉畫面
    D. 只執行一次新的協程而不取消舊的
    答案:B

  5. 若對 LaunchedEffect 傳入固定值 true 作為 key,代表該區塊會如何執行?
    A. 只在首度進入 Composition 時執行一次
    B. 每次重組皆執行
    C. 完全不會執行
    D. 只在畫面旋轉時執行
    答案:A

  6. 在 ViewModel 內以 SharedFlow 傳遞事件到 UI,於 Composable 中使用 LaunchedEffect 收集的好處為?
    A. 可以在背景執行緒更新 UI
    B. 避免因重組而重複 collect,確保只收集一次
    C. 自動快取事件歷史
    D. 免去權限檢查流程
    答案:B

  7. 若在 Composable 函式主體直接呼叫 collect(),最大風險是?
    A. collect 會被忽略
    B. Flow 會停止發射
    C. 每次重組都重新收集,導致記憶體與執行緒浪費
    D. 編譯不會通過
    答案:C

  8. rememberCoroutineScope 所回傳的 CoroutineScope 具有什麼生命週期?
    A. 與整個應用程式存活時間相同
    B. 與當前 Composable 的 Composition 存活時間相同,離開時自動取消
    C. 與 Activity 相同
    D. 與 ViewModel 相同
    答案:B

  9. 哪一個場合最適合使用 rememberCoroutineScope?
    A. 在 onClick 回呼中啟動短暫的協程
    B. 長時間的資料同步作業
    C. 循環播放音樂服務
    D. 伴隨應用程式整體生命週期的監控
    答案:A

  10. 在按鈕 onClick 裡啟動協程時,以下何者為最佳寫法?
    A. GlobalScope.launch { … }
    B. rememberCoroutineScope().launch { … }
    C. Thread { … }.start()
    D. LaunchedEffect(key1 = Unit) { … }
    答案:B

  11. 為何不建議在 Composable 外層大量使用 rememberCoroutineScope 啟動長任務?
    A. Compose 不支援協程
    B. 該 Scope 只活在 UI 層,長任務更適合 ViewModelScope
    C. Kotlinx.coroutines 不穩定
    D. 會強制使用主執行緒
    答案:B

  12. rememberUpdatedState 的功能是?
    A. 固定某個狀態值不再更新
    B. 提供可變的 State,避免觸發重組
    C. 在 effect 區塊中取得最新的參數或 lambda 引用,而不重新啟動協程
    D. 建立具自動取消能力的 Channel
    答案:C

  13. 在啟動畫面中,若 onTimeout Lambda 可能被替換,但不希望延長計時,應怎麼做?
    A. 將 onTimeout 直接放進 key
    B. 使用 rememberUpdatedState 包裝 onTimeout,並保持 key 固定
    C. 將計時邏輯搬到 Activity
    D. 改用 Handler.postDelayed
    答案:B

  14. 使用 rememberUpdatedState 後,要在 LaunchedEffect 中取得最新 Lambda,應該?
    A. 直接呼叫原來的 lambda 變數
    B. 透過 updatedLambda.value()
    C. 使用 by 委託取得 updatedLambda,再呼叫它
    D. 不可能取得最新值
    答案:C

  15. 若使用 Animatable 搭配 LaunchedEffect 實作數字動畫,應該把哪個值作為 key?
    A. Animatable 物件本身
    B. 當前計數器(counter)的 State 值
    C. rememberCoroutineScope
    D. viewModelScope
    答案:B

  16. LaunchedEffect 區塊會在何種情況被取消?
    A. 當 key 發生變化
    B. 當螢幕熄滅
    C. 當其他 Composable 產生副作用
    D. 永遠不會被取消
    答案:A

  17. 相較於 rememberCoroutineScope,viewModelScope 更適合長時間任務,原因為?
    A. viewModelScope 使用多執行緒池
    B. 其生命週期與 ViewModel 對應,較不易被 UI 銷毀
    C. viewModelScope 自動重試失敗任務
    D. Compose 強制要求
    答案:B

  18. 若在 Composable 中直接 collect Flow,可能造成下列何者?
    A. Flow 只會收集一次
    B. 當前協程會阻塞主執行緒
    C. 每次重組皆重啟收集,導致重複或洩漏
    D. Flow 會自動轉為 StateFlow
    答案:C

  19. 若想保證 LaunchedEffect 區塊只在入場時收集一次 Flow,key 應該如何設置?
    A. 不傳 key
    B. 傳入 MutableState 物件
    C. 傳入固定值 true 或 Unit
    D. 傳入當前時間戳
    答案:C

  20. 在 Jetpack Compose 中,哪一種情況會觸發 recomposition?
    A. 按下手機電源鍵
    B. State 或 MutableState 的值改變
    C. 裝置連線到 Wi‑Fi
    D. 從背景回到前景
    答案:B

  21. LaunchedEffect 本身是什麼?
    A. 一個不可重用的類別
    B. 一個 composable 函式,必須在 Composable 範圍內使用
    C. 一個 Android Service
    D. 一個 View 類別
    答案:B

  22. 在幾種 effect handler 中,下列哪個被視為最常使用?
    A. DisposableEffect
    B. LaunchedEffect
    C. SideEffect
    D. ProduceState
    答案:B

  23. 若要避免重組導致重複執行網路呼叫,應該使用哪個 effect handler 包裹?
    A. LaunchedEffect
    B. rememberUpdatedState
    C. SideEffect
    D. rememberCoroutineScope
    答案:A

  24. 透過 rememberCoroutineScope 啟動的協程,在 Composable 離開 Composition 時會?
    A. 自動取消
    B. 持續運行到應用結束
    C. 轉移至 Service
    D. 暫停並在回來時繼續
    答案:A

  25. LaunchedEffect 可以放在下列何處?
    A. 任何 Kotlin 檔案
    B. Service onCreate
    C. 只能置於 Composable 函式內
    D. BroadcastReceiver
    答案:C

  26. 需要在 effect 區塊內取得最新 lambda 實例,但又不想重新創建協程,應該採用?
    A. key = lambda
    B. rememberUpdatedState
    C. GlobalScope.launch
    D. DisposableEffect
    答案:B

  27. 若 LaunchedEffect 的 key 不含可能變動的 lambda,而 lambda 本身卻被替換,會導致?
    A. 協程自動更新 lambda
    B. 協程持續使用舊的 lambda,邏輯錯誤
    C. 編譯失敗
    D. lambda 被 GC 回收
    答案:B

  28. 在 UI 回呼(如 onClick)中正確啟動 coroutine 的方式是哪一個?
    A. viewModelScope.launch
    B. rememberCoroutineScope().launch
    C. LaunchedEffect(Unit) { }
    D. runBlocking { }
    答案:B

  29. 不當的副作用實作可能產生的後果包括?
    A. 記憶體洩漏與重複網路請求
    B. 編譯速度變慢
    C. APK 體積增大
    D. 減少程式碼行數
    答案:A

  30. LaunchedEffect 與 rememberCoroutineScope 的主要差異為何?
    A. 前者屬於 Composable 區塊,後者回傳 Scope 供回呼使用
    B. 前者只能用於回呼,後者只能用於 Effect
    C. 兩者完全相同
    D. rememberCoroutineScope 會自動重試協程
    答案:A

  31. 在 DisposableEffect 中,關於 onDispose 區塊的敘述何者正確?
    A. 必須與 rememberCoroutineScope 結合使用
    B. 僅在 key 為 null 時才需要實作
    C. 用於在 Composable 離開 Composition 時釋放資源
    D. 僅能呼叫非同步(suspend)函式
    答案:C

  32. 當 DisposableEffect 的 key 改變時,Compose 的行為為何?
    A. 重新執行 effect 區塊,且先執行 onDispose
    B. 直接取代舊區塊,不呼叫 onDispose
    C. 什麼都不做
    D. 僅在下一次重組時才移除舊區塊
    答案:A

  33. 下列哪個情境最適合使用 DisposableEffect?
    A. 每秒發射 UI 值
    B. 建立並移除 LifecycleObserver
    C. 快取複雜計算結果
    D. 監聽 State 改變並轉為 Flow
    答案:B

  34. DisposableEffect 與 LaunchedEffect 的主要差異為何?
    A. LaunchedEffect 可定義 onDispose,DisposableEffect 不行
    B. DisposableEffect 支援清理機制,LaunchedEffect 不支援
    C. 兩者皆不可傳入 key
    D. LaunchedEffect 只能在 Activity 內使用
    答案:B

  35. 若要在 ViewModel 層監聽 Lifecycle 而非 UI 層,應使用?
    A. LaunchedEffect
    B. DisposableEffect
    C. LifecycleObserver 於 ViewModelScope
    D. ProduceState
    答案:C

  36. SideEffect 會於哪個時機被呼叫?
    A. 每次成功完成 recomposition 後
    B. 每個畫面旋轉事件發生時
    C. 組成剛開始時
    D. 只有當 key 改變時
    答案:A

  37. SideEffect 的理想用途為?
    A. 快取大量資料
    B. 更新非 Compose 狀態或第三方 SDK 屬性
    C. 處理複雜動畫
    D. 監聽 Lifecycle
    答案:B

  38. SideEffect 區塊是否允許執行 suspend 函式?
    A. 允許,因內部有 CoroutineScope
    B. 不允許,只能執行同步程式碼
    C. 允許,但僅限 IO coroutine
    D. 允許,需搭配 rememberCoroutineScope
    答案:B

  39. 如果需要將 Compose 的 State 轉換成 Flow,以便套用 Flow 運算子,應使用?
    A. collectAsState
    B. produceState
    C. snapshotFlow
    D. derivedStateOf
    答案:C

  40. snapshotFlow 與 collectAsState 的功能關係為?
    A. 兩者皆將 Flow 轉為 State
    B. snapshotFlow 將 State 轉為 Flow;collectAsState 將 Flow 轉為 State
    C. 兩者皆將 State 轉為 Flow
    D. snapshotFlow 僅支援 StateFlow
    答案:B

  41. snapshotFlow 產生的 Flow 具有下列哪項特性?
    A. 永遠是熱流 (Hot)
    B. 僅在有收集者時監聽 State 變更
    C. 預設緩衝 100 個元素
    D. 會自動重播前 5 個值
    答案:B

  42. 在 snapshotFlow 中使用 distinctUntilChanged() 的主要目的為?
    A. 避免重複發射相同值
    B. 自動切換到 IO 執行緒
    C. 加速重組流程
    D. 將冷流轉為熱流
    答案:A

  43. produceState 的初始值指定方式為?
    A. 於呼叫端指定 initialValue 參數
    B. 在區塊內用 emit(0)
    C. 於 CoroutineScope.launch 裡設定
    D. 使用 remember 更新
    答案:A

  44. produceState 與 LaunchedEffect 皆可啟動 Coroutine;produceState 額外提供?
    A. 清理機制
    B. 直接回傳可觀察的 State 物件
    C. 監聽 Lifecycle 事件
    D. 轉換 State 為 Flow
    答案:B

  45. 若要每秒更新 UI 上的倒數計時器,最佳做法為?
    A. LaunchedEffect + State
    B. DisposableEffect
    C. produceState 回傳 State
    D. SideEffect
    答案:C

  46. derivedStateOf 的核心作用是?
    A. 將 State 轉為 Flow
    B. 快取依賴其他 State 的計算結果
    C. 提供 Lifecycle 清理點
    D. 發射 State 至外部 SDK
    答案:B

  47. 若 derivedStateOf 內部依賴的 State 未變動,但多個 Composable 讀取該值,Compose 會?
    A. 每次讀取皆重新計算
    B. 使用先前快取值,不重算
    C. 重新啟動整個重組
    D. 觸發 SideEffect
    答案:B

  48. 在 derivedStateOf 區塊內執行昂貴計算可帶來何種效益?
    A. 每次讀取都避免計算
    B. 減少不必要的 recomposition 計算負擔
    C. 自動轉換為 Lazy 計算
    D. 讓 CoroutineScope 自動管理
    答案:B

  49. 若 derivedStateOf 內僅讀取常數,而無任何可觀察 State,其計算會?
    A. 每次重組都執行
    B. 只執行一次並快取
    C. 從不執行
    D. 直到 onDispose 才執行
    答案:B

  50. 若需要在 Composable 離開畫面時自動移除觀察者並取消協程,應選用?
    A. GlobalScope.launch
    B. DisposableEffect
    C. SideEffect
    D. snapshotFlow
    答案:B

  51. 下面哪一個 effect handler 不支援傳入 key?
    A. DisposableEffect
    B. LaunchedEffect
    C. SideEffect
    D. produceState
    答案:C

  52. DisposableEffect 的 onDispose 區塊內適合執行何種操作?
    A. 建立資料庫連線
    B. 停止位置更新並移除回呼
    C. 更新 UI 文本
    D. 執行複雜計算並快取
    答案:B

  53. SideEffect 是否能保證在 recomposition 失敗時被呼叫?
    A. 能
    B. 無此保證
    C. 只有在 key 改變時才保證
    D. 取決於編譯器最佳化
    答案:B

  54. 當 snapshotFlow 觀察的 State 連續快速變動時,Flow 會?
    A. 丟棄中間值、只保留最新
    B. 預設全部發射,除非進一步操作
    C. 自動壓縮成集合
    D. 停止發射
    答案:B

  55. 若 snapshotFlow 內部引用的 State 被移除 Composition,Flow 會?
    A. 永遠持續發射
    B. 自動完成 (complete)
    C. 轉為熱流
    D. 崩潰並拋出例外
    答案:B

  56. produceState 區塊若需要釋放資源,應如何處理?
    A. 直接呼叫 cancel()
    B. 在區塊結尾使用 awaitClose
    C. 透過 DisposableEffect 包裹並於 onDispose 清理
    D. 不可能清理
    答案:C

  57. 何時應避免使用 SideEffect?
    A. 僅需一次性初始化
    B. 每次 recomposition 都必須同步外部物件
    C. 需要使用 suspend 函式、長時間作業
    D. 同步非 Compose 狀態
    答案:C

  58. 對 derivedStateOf 使用 by 委託 (val foo by derivedStateOf { }) 的好處為?
    A. 自動快取並提供可讀屬性
    B. 強制執行在 IO 執行緒
    C. 隱藏 StateFlow 細節
    D. 能自動清理
    答案:A

  59. DisposableEffect 的 key 採用 LifecycleOwner 的意義在於?
    A. 每次 Activity 旋轉都執行 onDispose/onCreate
    B. 保證 Observer 與正確的 Lifecycle 綁定
    C. 只要畫面亮起就會重設
    D. 避免產生多餘的 Snapshot
    答案:B

  60. 如果必須同時利用 Flow 運算子與 Compose State,以下組合最佳為?
    A. collectAsState → snapshotFlow → SideEffect
    B. snapshotFlow → Flow 運算子 → collectAsState
    C. derivedStateOf → DisposableEffect → GlobalScope
    D. produceState → DisposableEffect → snapshotFlow
    答案:B

Terminology

  • side effect: 在Jetpack Compose中,副作用是指那些超出可組合函數範圍的操作。例如,在可組合函數中進行網絡請求,會導致該函數每次重組成時都重新執行該網絡請求,這是需要避免的。
  • LaunchedEffect: 這是一種在可組合函數中執行異步操作的效果處理器。例如,用於啟動一個協程來執行延遲或網絡請求,並確保這些操作不會隨著重組成而多次執行。
  • Composable function: Jetpack Compose中的可組合函數,是用於定義UI的基本單元,允許UI的聲明式構建和重組。
  • recomposition: 當可組合函數中的狀態發生變化時,Jetpack Compose會重新執行該函數,以反映最新的狀態變化,這個過程稱為重組成。
  • Coroutine scope: 協程作用域,用於管理協程的生命週期,確保協程在適當的時機被取消。
  • suspend function: 一種可以在協程中調用的函數,允許在不阻塞線程的情況下執行異步操作。
  • SharedFlow: 一種流,允許多個收集器在不遺失事件的情況下共享數據,用於從ViewModel向UI層傳遞事件。
  • State: Compose中的狀態是用於保存和管理UI狀態的對象,當狀態改變時會觸發重組成。
  • Animatable: 一個可動畫的數值對象,允許對數值進行動畫操作。
  • effect handlers: 在Jetpack Compose中用於管理和執行副作用的工具,例如LaunchedEffect。
  • ViewModel: Android架構組件之一,用於管理UI相關的數據,並保持它們在配置變更(如旋轉屏幕)期間持續存在。
  • collect: 在Kotlin中,用於收集Flow流中的數據。
  • Flow: 一種Kotlin協程的API,用於表示異步數據流,可以發射多個值。
  • key: 在LaunchedEffect中使用的一個參數,用於控制效果的重啟行為,當key的值改變時,效果會重新啟動。
  • compose state: Jetpack Compose中的狀態,用於描述UI的當前狀態,並在狀態變更時觸發重組成。
  • lambda: 匿名函數,允許在簡短的上下文中定義行為。
  • animation: 在Jetpack Compose中,用於在UI元素之間過渡的動畫效果。
  • snackbar: 一種短暫顯示的消息條,用於向用戶提供反饋或提示。
  • nav controller: 用於管理應用程序內導航的控制器,幫助在不同屏幕之間進行導航。
  • rememberCoroutineScope: 在 Jetpack Compose 中,rememberCoroutineScope 是一個用於創建協程(Coroutine)作用域的函數。它允許在組件(composable)中創建協程,並在該組件生命週期結束時取消所有未完成的協程。這有助於避免在組件重新構建時發起多個重複的協程。
  • 協程(Coroutine): 協程是 Kotlin 中用於非同步編程的輕量級機制,類似於線程但更有效率。它允許在代碼中簡潔地處理非同步任務,如網絡請求或長時間運行的計算,而不會阻塞主線程。
  • 作用域(Scope): 在這裡指的是協程的執行範圍。使用 rememberCoroutineScope 創建的作用域會與組件的生命週期綁定,當組件不再可見或結束時,其內部的協程也會被取消。
  • 回調函數(Callbacks): 指的是例如 onClickonTextChanged 等在用戶操作或界面事件觸發時調用的函數。在這些回調函數中使用 rememberCoroutineScope 是安全的,因為它們不與組件的重新構建相關聯,不會導致多次不必要的協程啟動。
  • ViewModel: 在具有良好架構的應用程序中,通常建議使用 ViewModel 來處理業務邏輯和維護狀態。ViewModel 已經有自己的作用域,因此在大多數情況下,可以通過 ViewModel 的作用域來管理協程,而不必使用 rememberCoroutineScope
  • 啟動屏幕(splash screen): 應用程序啟動時顯示的介面,通常用於顯示品牌標誌或應用程序名稱,提供短時間的歡迎畫面。
  • Lambda 函數: 匿名函數或可以作為參數傳遞的函數。
  • onTimeout: 在啟動屏幕顯示一段時間後觸發的函數,用於處理啟動屏幕隱藏或其他相關操作。
  • key: 在 Compose 中用於區分和管理效果(effect)的唯一識別符。
  • rememberUpdatedState: Compose 中的一個 hook 函數,用於在狀態更新時通知 Compose 重新計算。當你需要在保持效果不重新啟動的同時更新依賴的狀態時,特別有用。
  • delegate: 在 Kotlin 中,委託(delegate)是一種模式,允許你將一些職責委託給另一個對象。在這裡,使用 rememberUpdatedState 作為一種委託方式來管理狀態。
  • 生命周期事件觀察者(Lifecycle Event Observer):用於在 Compose 中截取生命周期事件,例如當活動進入暫停狀態時進行相應操作,如打印日誌或其他處理。
  • 啟動效果(launch effect):在 Compose 中一種用於處理副作用的機制,可以通過指定鍵(key)來管理效果的生命週期,但無法用於需要清理的場景。
  • 一次性效果(disposable effect):與啟動效果類似,但是可以通過實現 onDispose 函數來清理資源,特別適用於需要在 Compose 組件結束時進行清理的場景,例如移除生命周期監聽器。
  • 生命周期所有者(lifecycle owner):通常指的是活動(Activity)或片段(Fragment),在 Android 中用於管理生命周期事件的對象。
  • 添加觀察者(addObserver):將生命周期事件觀察者添加到生命周期所有者中,以接收相應的生命周期事件通知。
  • 移除觀察者(removeObserver):從生命周期所有者中移除生命周期事件觀察者,避免資源泄漏或不必要的事件通知。
  • 清理資源(cleanup):在 Compose 組件不再需要某些資源時進行相應的清理工作,通常用於處理回調函數等需要額外管理的資源。
  • 副作用(side effect):在 Compose 中,一種特定的效果處理機制,用於在組件成功重構時執行指定的 Lambda 區塊。
  • 非 Compose 狀態(non-Compose state):指的是不符合 Compose 管理狀態的資料或狀態,例如從 API 或第三方庫中獲取的數據。
  • 重構(recompose):Compose 中組件重新計算和渲染的過程,通常由於相依的狀態或數據改變而觸發。
  • Firebase 使用者 ID(Firebase user ID):Firebase 提供的用於識別和管理用戶的唯一識別符。
  • 分析(analytics):在軟體開發中,指的是收集、處理和分析用戶行為和應用性能的過程。
  • Android 團隊文檔(Android team documentation):官方 Android 開發文檔,提供了關於使用 Android 框架和庫的指導和範例。
  • Produce State:這是一個可組合函數,返回一個produceState函數。該函數的目的是生成隨時間變化的某種狀態,類似於Flow。
  • Coroutine Scope:produceState函數提供了一個協程範疇,可以在其中調用掛起函數(如delay)。
  • Flow:一種可以發射多個值的Kotlin流式處理,這些值隨時間變化。使用Flow可以實現連續發射數據的功能。
  • Collect as State:這是一種從Flow收集數據並將其轉換為Compose中的狀態的方法。
  • Initial Value:初始化值,這裡指的是Flow或狀態初始的數值。
  • Derived State Of:這是一個可組合函數,用於創建派生狀態。它會在第一次訪問時計算並緩存結果,以後的訪問將使用緩存的值,除非依賴的狀態發生變化。
  • Counter State:一個初始值為0的計數狀態,表示計數器的當前值。
  • Counter Text:一個顯示計數器當前值的文本。每次計數器更新時,這段文本會重新計算並更新。
  • Recomputed:重新計算,指的是每次計數器狀態更新時,與計數器相關的文本也會重新計算。
  • Cache:緩存,指的是將計算結果存儲起來,後續訪問時使用緩存的結果而不是重新計算。
  • Concatenation:串聯操作,指的是將字符串和整數組合在一起的操作。
  • Complex Action:複雜操作,指的是需要依賴狀態並進行大量計算的操作。
  • Notify Composables:通知可組合函數,當派生狀態的依賴狀態發生變化時,自動通知相關的可組合函數進行更新。
  • Snapshot Flow:這是一個可組合函數,用於將Compose狀態轉換為Flow。當Compose狀態變化時,它會發出值。
  • Collect as State:這是一個從Flow收集數據並將其轉換為Compose中的狀態的方法。
  • Scaffold State:這是一個Compose中的狀態,通常包含UI佈局相關的狀態,例如SnackBarHostState。
  • SnackBarHostState:這是一個Compose中的狀態,用於管理SnackBar的顯示狀態。
  • Map:這裡指的是Flow的操作符,用於將一個值轉換為另一個值。
  • Distinct Until Changed:這是一個Flow的操作符,用於僅在值發生變化時才觸發新的發射。
  • Flow Operators:這些是用於處理Flow中數據的操作符,例如mapfilterdistinctUntilChanged等。
  • Reactive Programming:這是一種編程範式,強調數據流和變化傳播,通常使用Flow或RxJava等工具來實現。
  • Side Effect:在可組合函式之外改變狀態或執行 I/O 的動作,可能於不受控時間重複觸發
  • Composable Function:Jetpack Compose 中可宣告 UI 的函式,具備可重組能力
  • Recomposition:框架偵測狀態變化後重新執行可組合函式以更新 UI 的過程
  • Jetpack Compose:Android 宣告式 UI 工具包,以 Kotlin DSL 描述介面
  • Effect Handler:Compose 提供的 API,用於安全地執行副作用並管理生命週期
  • LaunchedEffect:以 key 為依據啟動及取消協程的 effect handler,常用於一次性或鍵值變動時的副作用
  • rememberCoroutineScope:回傳與組合生命週期綁定的協程範圍,適合在回呼中啟動協程
  • rememberUpdatedState:保存最新物件參考,在不重新啟動協程的情況下提供更新值
  • Coroutine:Kotlin 的輕量級非同步執行單元,支援掛起與取消
  • CoroutineScope:限定協程生命週期與錯誤傳播邊界的容器
  • Suspend Function:可掛起與恢復的函式,允許在協程內非阻塞呼叫
  • Flow:冷流資料串流類型,按需發射序列值
  • SharedFlow:熱流,可多播事件給多個收集者
  • State:Compose 的可觀察資料類型,變更時觸發重組
  • MutableState:可變版 State,透過 setter 更新值
  • Animatable:用於在協程中平滑插值數值的可動畫對象
  • remember:在重組間保留物件,僅於首次組合時初始化
  • Key:傳給 effect handler 的辨識值,用來決定是否重啟副作用
  • Scaffold:提供一致佈局結構(如 AppBar、FAB)之組合容器
  • SnackbarHostState:管理 Snackbar 顯示佇列的狀態物件
  • NavController:Navigation Compose 的導覽控制器,負責畫面轉換
  • ViewModel:儲存 UI 狀態並持有商業邏輯的生命週期感知類別
  • viewModelScope:與 ViewModel 同生共死的協程範圍,適合執行背景任務
  • launch:在指定 CoroutineScope 內啟動新的協程建構器
  • collect:在協程中取得 Flow 發射的值並處理
  • cancel:停止協程並觸發取消例外,防止資源浪費
  • delay:非阻塞地暫停協程指定時間
  • Callback:事件回呼函式,於使用者互動或流程完成時觸發
  • onClick:元件被點擊時呼叫的 Lambda 回呼
  • Lambda:Kotlin 的匿名函式表示法,可作為一級公民傳遞
  • rememberSaveable:可跨組成和組件重建保存狀態的輔助函式
  • Snapshot:Compose 內部不可變狀態快照,用於一致性檢查
  • CompositionLocal:在組合層級注入與取得依賴的機制
  • rememberInfiniteTransition:建立無窮動畫的狀態容器
  • DisposableEffect:用於建立並清理需要明確釋放資源的副作用
  • SideEffect(組合器):於重組後一次性執行程式區段的 API
  • produceState:外部資料源轉換為 Compose State 的協助函式
  • derivedStateOf:根據其他 State 推導衍生 State,具備快取能力
  • snapshotFlow:將 Snapshot 讀取轉換為 Flow,便於收集狀態變更
  • rememberMutableStateListOf:建立可追蹤變動的可變 List 狀態
  • EffectPhase:Compose 執行階段,分為應用、佈局、繪製等階段
  • Composition:Compose 建構與維護 UI 節點樹的過程
  • rememberLauncherForActivityResult:封裝 Activity 結果 API 的 compose 幫手
  • coroutineContext:協程執行環境集合,包括 Job、Dispatcher 等元素
  • CancellationException:協程被取消時拋出的例外,可攔截釋放資源
  • 同步 (Blocking):呼叫執行期間執行緒被占用,等待結果返回
  • 非同步 (Non‑blocking):呼叫立即返回,結果於未來時間點提供
  • Cold Flow:直到收集者訂閱才開始發射資料的 Flow
  • Hot Flow:無論是否有收集者都持續發射的流類型
  • Backpressure:下游處理速度不足時的流量控制問題
  • 宣告式 (Declarative):以描述「呈現什麼」為主的 UI 範式
  • 命令式 (Imperative):以描述「如何做」的傳統 UI 更新方式
  • DisposableEffect:在組合階段建立副作用並要求提供 onDispose 回收邏輯的效應處理器
  • onDispose:DisposableEffect 內必實作區塊,於可組合項離開組合樹時執行清理程式碼
  • LifecycleEventObserver:觀察 Activity/Fragment 生命週期轉換並回傳事件的介面
  • LifecycleOwner:提供 Lifecycle 以供觀察者註冊的持有者(如 Activity 或 Fragment)
  • Lifecycle.State:描述元件當前所處的生命週期狀態列舉,例如 RESUMED、PAUSED
  • Composition Exit:可組合項從組合樹移除的階段,適合釋放資源
  • rememberObserver:以 remember 儲存生命週期觀察者,避免重組時重複建立
  • SideEffect(API):於成功重組後僅執行一次區塊,用以同步非 Compose 狀態
  • Atomic Snapshot:Compose 執行快照,確保狀態一致性與執行緒安全
  • SnapshotAppliedCallback:快照套用完畢後觸發的回呼,可追蹤狀態提交
  • produceState:以協程產生可隨時間變化的 State,並自動重新組合使用者
  • initialValue 參數:produceState 的初始值,用作第一次組合前的回傳
  • Coroutine Cancellation:透過 Job.cancel() 終止協程並釋放資源
  • MutableStateFlow:熱流實作,具備高階別同步狀態能力並支援重播
  • MutableSharedFlow:通用事件匯流,可設定緩衝與重播策略供多消費者使用
  • distinctUntilChanged:Flow 運算子,過濾連續重複值避免多餘發射
  • snapshotFlow 轉換:將可組合 State 封裝為 Flow,在狀態改變時發射
  • FlowCollector:收集 Flow 發射元素的介面,執行處理邏輯
  • BackpressureStrategy:控制生產速率超過消費速率時的處置方式
  • derivedStateOf:根據其他 State 推導衍生值並快取,僅於依賴變動時重算
  • ReadObserver:監聽 State 被讀取以便追蹤依賴關係的內部機制
  • StructuralEqualityPolicy:Compose 預設比較策略,值內容相同即視為無變化
  • ReferentialEqualityPolicy:使用參考比較避免深度比較提升效能
  • Snapshot Invalidation:狀態改變導致快照失效,需要重新計算依賴
  • SuspensionPoint:協程暫停等待非阻塞結果的位置
  • rememberInfiniteTransition:管理無限動畫狀態並在重組間保留
  • animate*AsState:根據目標值平滑插值並回傳可組合的動畫 State
  • key1、key2 參數:LaunchedEffect 等 API 的鍵值,用於判斷是否重啟副作用
  • DisposableEffectResult:onDispose 區塊返回型別,代表清理操作執行結果
  • NonRestartableComposable:標註可組合項不可在熱重新載入期間重啟的註解
  • rememberSaveableStateHolder:在多重導航層級保存/恢復 State 的輔助類
  • MapState:將 Map 包裝為可觀察 State,隨鍵值改變觸發重組
  • produceLazyPagingItems:將 PagingData 轉為 Compose 列表專用狀態容器
  • LaunchedEffect keySet:可傳入變動集合做為鍵值,集合內容改變即重啟協程
  • SnapshotMutationPolicy:自訂狀態比較與變異合法性的策略介面
  • runningRecomposeScopes:Compose Runtime 追蹤當前進行中的重組範圍集合
  • DisposableScope:DisposableEffect 提供的作用域,允許存取 CoroutineScope
  • CompositionLocalProvider:注入本地依賴至組合階層,供子組合使用
  • rememberUpdatedState λ:保持最新 Lambda 參考以避免重啟協程
  • AndroidViewBinding:Compose 內嵌傳統 View 並透過 ViewBinding 操作
  • ScrollState:可組合捲動狀態,提供偏移與控制函式
  • DerivedState Recalculation:依賴變動觸發 derivedStateOf 重新計算快取
  • Ambient Recomposition:基於 CompositionLocal 依賴變動觸發的重組
  • rememberCoroutineContext:取得與當前組合關聯的協程上下文
  • snapshotFlow Buffering:可對 snapshotFlow 設定緩衝避免丟失高頻事件
  • coroutineScope{} 建構器:在掛起函式內建立子作用域並等待其完成
  • DisposableEffectScope:提供 addDisposeListener 等 API 增強清理能力的範圍
  • registerForActivityResult:封裝系統 Activity 回傳結果的 API,可結合 rememberLauncherForActivityResult
  • Compose Runtime:負責比對、排程與執行重組邏輯的核心
  • StateSnapshotHandle:保存快照狀態與版本資訊,用於衝突偵測