今天,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 现在可实现与使用 View 相同的性能:
滚动性能基准比较了不同版本的 Compose 中 View 和 Jetpack Compose 的性能
延迟预提取中的可暂停组合
现在,延迟预提取中的可暂停组合已默认处于启用状态。这是对 Compose 运行时调度工作方式的根本性更改,旨在显著减少繁重界面工作负载期间的卡顿。
以前,一旦组合开始,就必须运行到完成。如果合成较为复杂,则可能会阻塞主线程的时间超过单个帧,从而导致界面冻结。借助可暂停的组合,如果运行时时间不足,现在可以“暂停”其工作,并在下一帧中恢复工作。与延迟布局预取搭配使用时,这种做法尤其有效,可提前准备好帧。Compose 1.9 中引入的延迟布局 CacheWindow API 是一种预提取更多内容的好方法,可利用可暂停的组合来获得更流畅的界面性能。
可暂停组合与延迟预提取相结合,有助于减少卡顿
我们还优化了其他方面的性能,改进了 Modifier.onPlaced、Modifier.onVisibilityChanged 和其他修饰符实现。我们会继续投入资源来提升 Compose 的性能。
新功能
保留
Compose 提供了许多 API 来在不同生命周期中保持和管理状态;例如,remember 可在重组期间保持状态,而 rememberSavable/rememberSerializable 可在重新创建 activity 或进程期间保持状态。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,包括更新用于自定义共享元素动画的 API。
动态共享元素
默认情况下,sharedElement() 和 sharedBounds() 动画会尝试为
每当在目标状态中找到匹配的键时,布局都会发生变化。不过,您可能希望根据某些条件(例如导航方向或当前界面状态)动态停用此动画。
如需控制是否发生共享元素过渡,您现在可以自定义传递给 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,这与生产行为不同;例如,效果可能会立即运行,而不是排队等待。在未来的版本中,我们计划推出一个默认使用 StandardTestDispatcher 的新 API,以匹配生产行为。您可以在 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 开发者新增了多项功能:
-
转换界面:通过以下方式迭代设计:右键点击
@Preview,选择“转换界面”,然后用自然语言描述更改。 -
生成
@Preview:右键点击可组合项,然后选择 Gemini > 生成 [可组合项名称] 预览。 - 在 Vector Asset 向导中新增了对图标变体的支持,可用于自定义 Material Symbols。
- 根据屏幕截图生成代码,或问问 Gemini 将现有界面与目标图片相匹配。这可以与远程 MCP 支持相结合,例如连接到 Figma 文件并从设计生成 Compose 界面。
- 修复界面质量问题会审核界面是否存在常见问题(例如无障碍问题),然后提出修复建议。
如需查看这些工具的实际应用,请观看以下最新演示:
祝您编程顺利
我们会继续投资于 Jetpack Compose,为您提供创建精美丰富界面的 API 和工具。我们非常重视您的意见,欢迎您在问题跟踪器中分享对这些变更的反馈,或提出您希望我们接下来做出的改进。
继续阅读
-
产品资讯
Android Studio Panda 4 现已是稳定版,可在生产环境中使用。此版本带来了规划模式、后续编辑预测等功能,让您能够比以往更轻松地构建高质量的 Android 应用。
Matt Dyor • 阅读用时:5 分钟
-
产品资讯
如果您是 Android 开发者,并希望在应用中实现创新的 AI 功能,那么我们最近推出的强大新更新将能满足您的需求。
Thomas Ezan • 阅读用时:3 分钟
-
产品资讯
Android 17 已达到 Beta 版 4,这是此发布周期的最后一个预定 Beta 版,也是应用兼容性和平台稳定性的重要里程碑。
Daniel Galpin • 阅读用时:4 分钟
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见。