網路城邦
上一篇 回創作列表 下一篇   字體:小 中 大
解析 Jetpack Compose 之 State
2026/09/24 22:39:36瀏覽148|回應0|推薦0

State 本質上只能自動觸發那些被 Compose 快照系統(Snapshot System)所監聽的特定 Scope(即 Restart / Invalidation Scopes),如果你在一個與 Compose 渲染管線(Composition、Layout、Draw)無關的普通 Kotlin 程式碼區塊內讀取 State,它的數值改變時,絕對不會自動觸發該區塊重新執行,這是因為 Compose 底層運作的本質是 「讀取追蹤(Read Tracking)」。

一. 什麼是 Compose 特定的 Scope?

在 Compose 底層,凡是能夠被 State 變更所觸發、重新執行的程式碼區塊,都被稱為 RestartScope(重啟範疇)。

當程式執行到這些 Scope 內部時,Compose 的快照系統會秘密地打開監聽器:「現在進來的代碼由我保護,裡面只要有讀取 mutableStateOf 或 Animatable,我就把它記錄在案。」

這些被官方認證、能夠觸發特定階段 Invalidate 的 Scope 包含:

  1. Recompose Scope(普通的 @Composable 函式體):觸發重組。
  2. Layout / Measure Scope(例如 Modifier.offset { ... } 或 Modifier.layout):觸發重新排版/測量。
  3. Draw Scope(例如 drawBehind 或 Canvas):觸發純重繪。

二. 超出這些 Scope,State 就會「失效」

如果你把 State 的讀取點放在以下這類 「非 Compose 監聽的普通 Scope」 內,當 State 改變時,它是完全保持沉默、不會觸發任何自動更新的:

範例 A:普通的 Kotlin 類別方法(非 Composable)

範例 B:手勢或點擊回呼的「執行當下」(事件處理範圍)

三. 如果想在「非 Compose 環境」監聽 State 怎麼辦?

如果你今天寫了一段純 Kotlin 的業務邏輯(例如在 ViewModel 裡,或者在自訂的數據處理器中),需要去捕捉 Compose State 的變動,Compose 有提供專門的橋接工具,把 State 轉換成標準的監聽流:

武器:snapshotFlow { ... }

這是將 Compose 狀態外拋給非 Compose 環境的唯一正統通道。它會把一個快照狀態轉換成 Kotlin 的 Flow:

四. Never-Equal Scope(高頻突變監聽範疇)

這是一種為了 144Hz 高頻觸控手勢或物理引擎刻意配置的「強制 Invalidate 機制」。

  • 觸發機制:無條件強行重繪或重組。
  • 底層行為:徹底打破 Compose 的緩存機制。普通 State 在新舊值相等時會攔截並吞掉更新。但加上 neverEqualPolicy() 後,只要執行賦值寫入,Compose 就會無條件判定數值已改變,百分之百、無漏失地向下游讀取點(如 DrawScope)發射重繪通知。

代表性代碼:

總結

Compose 的 State 就像是一台只在特定軌道上運行的磁浮列車。

  • 它只能精準通知並刷新 RecomposeScope、LayoutScope 和 DrawScope。
  • 一旦離開了這三大核心軌道(普通函數、回呼事件、一般類別),它的「自動刷新神力」就會完全消失。
( 知識學習|其他 )
推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=start8588&aid=192550357