本文译自「What's new in the Jetpack Compose December '25 release」,原文链接android-developers.googleblog.com/2025/12/wha...,由Nick Butcher发布于2025年12月3日。
现在,Jetpack Compose 2025年12月版本 正式发布。该版本包含 Compose 核心模块 1.10 版和 Material 3 1.4 版(参见完整的 BOM 映射),新增了 多项功能并显著提升了性能。
要使用最新的版本,请将 Compose BOM 版本升级到 2025.12.00:
kotlin
implementation(platform("androidx.compose:compose-bom:2025.12.00"))
性能改进
我们知道应用程序的运行时性能对你和你的用户至关重要,因此性能一直是 Compose 团队的首要任务。此版本带来了一系列改进------你只需升级到最新版本即可获得所有这些改进。我们的内部滚动性能基准测试表明,Compose 现在的性能与使用 Views 时的性能相当:

延迟预取中的可暂停组合
延迟预取中的可暂停组合预取功能现已默认启用。这是 Compose 运行时调度机制的一项根本性变革,旨在显著减少高 UI 负载下的卡顿现象。
此前,一旦合成开始,就必须运行至完成。如果合成较为复杂,则可能导致主线程阻塞超过一帧,从而造成 UI 卡顿。而现在,借助可暂停合成功能,运行时可以在时间不足时"暂停"其工作,并在下一帧恢复。当与延迟布局预取结合使用,提前准备帧时,此功能尤为有效。 Compose 1.9 中引入的 LazyLayoutCacheWindow API 可以很好地预取更多内容,并利用可暂停的合成功能来显著提升 UI 性能。
我们还优化了其他方面的性能,例如改进了 Modifier.onPlaced。 Modifier.onVisibilityChanged 和其他修饰符实现。我们将继续投入资源来提升 Compose 的性能。
新功能
Retain
Compose 提供了一系列 API 来跨不同的生命周期保存和管理状态;例如,remember 可以在组合之间持久化状态,而 rememberSavable/rememberSerializable 可以在 Activity 或进程重建之间持久化状态。retain 是一个介于这些 API 之间的新 API,它允许你在配置更改时持久化值而无需序列化,但不会跨进程终止。由于 retain 不会序列化你的状态,因此你可以持久化诸如 lambda 表达式、流程以及位图等难以序列化的大型对象。例如,你可以使用 retain 来管理媒体播放器(例如 ExoPlayer),以确保媒体播放不会因配置更改而中断。
kotlin
@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。Material Text 可组合元素现在支持自动调整大小功能(autoSize)。
-
轮播组件现在提供了一个新的 HorizontalCenteredHeroCarouselvariant。
-
TimePicker 现在支持在选择器模式和输入模式之间切换。
-
垂直拖拽手柄(VerticalDragHandle)帮助用户更改自适应空格的大小或者位置。

请注意,Material 3 Expressive API 仍在 Material 3 库的 alpha 版本中持续开发。要了解更多信息,请观看最近的演讲。
新的动画功能
我们持续扩展动画 API,包括对自定义共享元素动画的更新。
动态共享元素
默认情况下,sharedElement() 和 sharedBounds() 动画会在目标状态中找到匹配的键时尝试为布局更改添加动画效果。但是,你可能希望根据某些条件(例如导航方向或当前 UI 状态)动态禁用此动画。
要控制共享元素过渡是否发生,你现在可以自定义传递给 rememberSharedContentState() 的 SharedContentConfig。isEnabled 属性决定共享元素是否处于活动状态。
kotlin
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,允许你将初始速度(例如来自手势)传递给共享元素过渡:
kotlin
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 可组合元素出现或消失。新增的实验性遮罩选项允许你指定颜色来遮盖或修饰内容;例如,在内容上方淡入/淡出半透明黑色图层:

kotlin
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,这与生产环境的行为有所不同;例如,副作用可能会立即运行,而不是被放入队列。在未来的版本中,我们计划引入一个新的 API,默认使用 StandardTestDispatcher,以匹配生产环境的行为。你现在可以在 1.10 版本中尝试新的行为:
kotlin
@get:Rule // also createAndroidComposeRule, createEmptyComposeRule
val rule = createComposeRule(effectContext = StandardTestDispatcher())
使用 StandardTestDispatcher 会将任务放入队列,因此你必须使用同步机制,例如 composeTestRule.waitForIdle() 或 composeTestRule.runOnIdle()。如果你的测试使用了 runTest,则必须确保 runTest 和你的 Compose 规则共享同一个 StandardTestDispatcher 实例以进行同步。
kotlin
// 1. Create a SINGLE dispatcher instance
valtestDispatcher = StandardTestDispatcher()
// 2. Pass it to your Compose rule
@get:Rule
valcomposeRule = createComposeRule(effectContext = testDispatcher)
@Test
// 3. Pass the *SAME INSTANCE* to runTest
funmyTest() = runTest(testDispatcher) {
composeRule.setContent{/* ... */}
}
工具
优秀的 API 需要优秀的工具,Android Studio 为 Compose 开发者新增了多项功能:
-
变换 UI:右键单击 @Preview,选择"变换 UI",然后用自然语言描述更改,即可迭代你的设计。
-
生成 @Preview:右键单击可组合元素,然后选择 Gemini > 生成 [可组合元素名称] 预览。
-
自定义 Material Symbols:矢量资源向导新增了对图标变体的支持。
-
从屏幕截图生成代码 或让 Gemini 将你现有的 UI 与目标图像匹配。这可以与远程 MCP 支持 结合使用,例如连接到 Figma 文件并从设计生成 Compose UI。
-
修复 UI 质量问题 会审核你的 UI 是否存在常见问题,例如辅助功能问题,然后提出修复方案。
要查看这些工具的实际应用,请观看此 最新演示。
尽情创作
我们持续投入资源开发 Jetpack Compose,为你提供创建美观、丰富的用户界面所需的 API 和工具。我们重视你的反馈,请在我们的问题跟踪器中分享你对这些更改的反馈,或你希望看到的后续功能。
欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!
保护原创,请勿转载!