今天,Jetpack Compose 2025 年 12 月版已發布穩定版。這個版本包含核心 Compose 模組的 1.10 版和 Material 3 的 1.4 版 (請參閱完整的 BOM 對應),並新增多項功能及大幅提升效能。
如要使用今天的發布版本,請將 Compose BOM 版本升級至 2025.12.00:
implementation(platform("androidx.compose:compose-bom:2025.12.00"))
提升效能
我們瞭解應用程式的執行階段效能對您和使用者來說非常重要,因此效能一直是 Compose 團隊的首要任務。這個版本帶來多項改善,只要升級至最新版本,即可享有所有優勢。根據內部捲動基準,Compose 現在的效能與使用 Views 時的效能相同:
捲動效能基準,比較不同 Compose 版本中 Views 和 Jetpack Compose 的效能
延遲預先擷取時可暫停組合
系統現在預設啟用延遲預先擷取中的可暫停組合。這項重大變更會影響 Compose 執行階段排程的工作方式,目的是大幅減少高負載 UI 工作負載期間的卡頓。
先前,組合一旦開始,就必須執行完畢。如果組合複雜,可能會封鎖主執行緒的時間超過單一影格,導致 UI 凍結。有了可暫停的組合,如果執行階段時間不足,現在可以「暫停」工作,並在下一個影格繼續工作。如果搭配使用延遲版面配置預先擷取功能,提早準備影格,效果會特別顯著。Compose 1.9 推出的 Lazy 版面配置 CacheWindow API,可預先擷取更多內容,並利用可暫停的組合功能,大幅提升 UI 效能。
可暫停的組合搭配 Lazy prefetch,有助於減少卡頓
我們也改善了 Modifier.onPlaced、Modifier.onVisibilityChanged 和其他修飾符的實作方式,進一步提升效能。我們會持續投入資源,提升 Compose 的效能。
新功能
保留
Compose 提供多種 API,可跨不同生命週期保留及管理狀態;舉例來說,remember 會在重組時保留狀態,而 rememberSavable/rememberSerializable 則會在重新建立活動或程序時保留狀態。retain 是介於這些 API 之間的新 API,可讓您在設定變更時保留值,不必序列化,但不會跨程序終止。由於 retain 不會序列化狀態,因此您可以保存 lambda 運算式、Flow 和點陣圖等大型物件,這些物件不容易序列化。舉例來說,您可以使用 retain 管理媒體播放器 (例如 ExoPlayer),確保媒體播放不會因設定變更而中斷。
@Composable
fun MediaPlayer() {
val applicationContext = LocalContext.current.applicationContext
val exoPlayer = retain { ExoPlayer.Builder(applicationContext).apply { ... }.build() }
...
}
我們衷心感謝 AndroidDev 社群 (尤其是 Circuit 團隊),他們對這項功能的設計有深遠影響,並做出許多貢獻。
Material 1.4
material3 程式庫 1.4.0 版新增多項元件和強化功能:
TextField現在提供實驗性的TextFieldState基礎版本,可提供更穩健的文字狀態管理方法。此外,我們也提供新的SecureTextField和OutlinedSecureTextField變體。MaterialText可組合函式現在支援 autoSize 行為。- 輪播介面元件現在提供新的
HorizontalCenteredHeroCarousel變數。 TimePicker現在支援在挑選器和輸入模式之間切換。- 使用者可以透過垂直拖曳控點變更自適應窗格的大小和/或位置。
水平置中主頁橫幅輪轉介面
請注意,Material 3 Expressive API 仍會在 material3 程式庫的 Alpha 版中開發。詳情請參閱這場最近的演講:
全新動畫功能
我們持續擴充動畫 API,包括更新共用元素動畫的自訂功能。
動態共用元素
根據預設,sharedElement() 和 sharedBounds() 動畫會嘗試為
只要在目標狀態中找到相符的鍵,版面配置就會變更。不過,您可能會想根據特定條件 (例如導覽方向或目前的 UI 狀態),動態停用這項動畫。
如要控管是否發生共用元素轉場效果,現在可以自訂傳遞至 rememberSharedContentState() 的 SharedContentConfig。isEnabled 屬性會決定共用元素是否有效。
SharedTransitionLayout {
val transition = updateTransition(currentState)
transition.AnimatedContent { targetState ->
// Create the configuration that depends on state changing.
fun animationConfig() : SharedTransitionScope.SharedContentConfig {
return object : SharedTransitionScope.SharedContentConfig {
override val SharedTransitionScope.SharedContentState.isEnabled: Boolean
get() =
// determine whether to perform a shared element transition
}
}
}
詳情請參閱說明文件。
Modifier.skipToLookaheadPosition()
這個版本新增了 Modifier.skipToLookaheadPosition() 輔助鍵,可在執行共用元素動畫時,保留可組合項的最終位置。這樣就能執行「顯示」類型動畫等轉場效果,如 Androidify 範例中相機的漸進式顯示效果。如要瞭解詳情,請參閱這部影片:
共用元素轉場效果的初速度
本次發布內容新增了共用元素轉場效果 API prepareTransitionWithInitialVelocity,可將初始速度 (例如來自手勢) 傳遞至共用元素轉場效果:
Modifier.fillMaxSize()
.draggable2D(
rememberDraggable2DState { offset += it },
onDragStopped = { velocity ->
// Set up the initial velocity for the upcoming shared element
// transition.
sharedContentStateForDraggableCat
?.prepareTransitionWithInitialVelocity(velocity)
showDetails = false
},
)
從手勢開始,以初始速度進行共用元素轉場
遮蓋轉場效果
EnterTransition 和 ExitTransition 會定義 AnimatedVisibility/AnimatedContent 可組合函式的顯示或消失方式。新的實驗性遮罩選項可讓您指定遮罩或遮蓋內容的顏色,例如在內容上淡入/淡出半透明黑色圖層:
隱藏式動畫內容:請注意,動畫播放期間,格線內容會覆蓋半透明的遮罩 (或幕布)
AnimatedContent(
targetState = page,
modifier = Modifier.fillMaxSize().weight(1f),
transitionSpec = {
if (targetState > initialState) {
(slideInHorizontally { it } togetherWith
slideOutHorizontally { -it / 2 } + veilOut(targetColor = veilColor))
} else {
slideInHorizontally { -it / 2 } +
unveilIn(initialColor = veilColor) togetherWith slideOutHorizontally { it }
}
},
) { targetPage ->
...
}
近期異動
淘汰 Modifier.onFirstVisible
Compose 1.9 導入了 Modifier.onVisibilityChanged 和 Modifier.onFirstVisible。審查您的意見回饋後,我們發現無法確定是否能遵守 Modifier.onFirstVisible 的合約,具體來說,就是無法確定項目首次顯示的時間。舉例來說,如果項目捲動到檢視區塊外,Lazy 版面配置可能會捨棄這些項目,然後在項目捲動回檢視畫面時再次組合。在這種情況下,由於這是新組成的項目,因此 onFirstVisible 回呼會再次觸發。返回含有 onFirstVisible 的先前瀏覽畫面時,也會發生類似行為。因此,我們決定在下一個 Compose 版本 (1.11) 中淘汰這個修飾符,並建議遷移至 onVisibilityChanged。詳情請參閱說明文件。
測試中的協同程式調度
我們計畫變更測試中的協同程式調度,以減少測試不穩定性並找出更多問題。目前測試使用的是 UnconfinedTestDispatcher,這與實際運作行為不同,例如 effects 可能會立即執行,而不是加入佇列。我們計畫在日後發布新版 API,預設使用 StandardTestDispatcher 來比對正式環境的行為。您現在可以在 1.10 版中試用新版行為:
@get:Rule // also createAndroidComposeRule, createEmptyComposeRule val rule = createComposeRule(effectContext = StandardTestDispatcher())
使用 StandardTestDispatcher 會將工作排入佇列,因此您必須使用 composeTestRule.waitForIdle() 或 composeTestRule.runOnIdle() 等同步機制。如果測試使用 runTest,請務必確保 runTest 和 Compose 規則共用同一個 StandardTestDispatcher 執行個體,以進行同步處理。
// 1. Create a SINGLE dispatcher instance
val testDispatcher = StandardTestDispatcher()
// 2. Pass it to your Compose rule
@get:Rule
val composeRule = createComposeRule(effectContext = testDispatcher)
@Test
// 3. Pass the *SAME INSTANCE* to runTest
fun myTest() = runTest(testDispatcher) {
composeRule.setContent { /* ... */ }
}
工具
優質的 API 值得搭配優質工具,而 Android Studio 最近也為 Compose 開發人員新增了多項功能:
- 轉換 UI:在
@Preview上按一下滑鼠右鍵,選取「轉換 UI」,然後以自然語言描述變更內容,即可疊代設計。 - 生成
@Preview:在可組合函式上按一下滑鼠右鍵,然後選取「Gemini」>「Generate [可組合函式名稱] Preview」。 - 自訂 Material Symbols:Vector Asset 精靈現在支援圖示變化版本。
- 從螢幕截圖生成程式碼,或問問 Gemini 將現有 UI 與目標圖片相符。這項功能可與遠端 MCP 支援搭配使用,例如連線至 Figma 檔案,並從設計生成 Compose UI。
- 「修正 UI 品質問題」會稽核 UI 的常見問題 (例如無障礙問題),然後建議修正方式。
如要查看這些工具的實際運作情形,請觀看這場近期的示範:
祝您編寫愉快!
我們將持續投入 Jetpack Compose,為您提供建立精美豐富 UI 所需的 API 和工具。我們很重視您的想法,歡迎在問題追蹤工具中分享對這些異動的意見,或提出您希望我們接下來推出的功能。
繼續閱讀
-
產品新訊
盡可能確保 Google Play 提供最安全可靠的服務體驗。今天,我們宣布推出一系列新政策和帳戶轉移功能,進一步保障使用者隱私,並防範詐欺行為。
Bennet Manuel • 3 分鐘可讀完
-
產品新訊
現在使用 Android Emulator,就能輕鬆測試支援多種裝置的互動。
Steven Jenkins • 閱讀時間:2 分鐘
-
產品新訊
每位開發人員的 AI 工作流程和需求都不盡相同,因此選擇 AI 輔助開發的方式非常重要。我們在 1 月推出這項功能,讓您選擇任何本機或遠端 AI 模型,為 Android Studio 中的 AI 功能提供支援
Matthew Warner • 閱讀時間:2 分鐘
隨時掌握最新消息
每週透過電子郵件接收最新的 Android 開發洞察資料。