Jetpack Compose 2025年12月版本新增功能

本文译自「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)。

  • 轮播组件现在提供了一个新的 Horizo​​ntalCenteredHeroCarouselvariant

  • TimePicker 现在支持在选择器模式和输入模式之间切换。

  • 垂直拖拽手柄(VerticalDragHandle)帮助用户更改自适应空格的大小或者位置。

请注意,Material 3 Expressive API 仍在 Material 3 库的 alpha 版本中持续开发。要了解更多信息,请观看最近的演讲

新的动画功能

我们持续扩展动画 API,包括对自定义共享元素动画的更新。

动态共享元素

默认情况下,sharedElement()sharedBounds() 动画会在目标状态中找到匹配的键时尝试为布局更改添加动画效果。但是,你可能希望根据某些条件(例如导航方向或当前 UI 状态)动态禁用​​此动画。

要控制共享元素过渡是否发生,你现在可以自定义传递给 rememberSharedContentState()SharedContentConfigisEnabled 属性决定共享元素是否处于活动状态。

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
			},
)

面纱过渡动画

EnterTransitionExitTransition 定义了动画的执行方式。 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.onVisibilityChangedModifier.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 开发者新增了多项功能:

要查看这些工具的实际应用,请观看此 最新演示

尽情创作

我们持续投入资源开发 Jetpack Compose,为你提供创建美观、丰富的用户界面所需的 API 和工具。我们重视你的反馈,请在我们的问题跟踪器中分享你对这些更改的反馈,或你希望看到的后续功能。

欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!

保护原创,请勿转载!

相关推荐
思成不止于此2 小时前
【MySQL 零基础入门】DQL 核心语法(二):表条件查询与分组查询篇
android·数据库·笔记·学习·mysql
安卓理事人6 小时前
安卓图表MpAndroidChart使用
android
奋斗的小鹰7 小时前
在已有Android工程中添加Flutter模块
android·flutter
介一安全8 小时前
【Frida Android】实战篇13:企业常用非对称加密场景 Hook 教程
android·网络安全·逆向·安全性测试·frida
lin62534229 小时前
Android右滑解锁UI,带背景流动渐变动画效果
android·ui
鹏多多11 小时前
Flutter输入框TextField的属性与实战用法全面解析+示例
android·前端·flutter
2501_9160088911 小时前
iOS 开发者工具全景图,构建从编码、调试到性能诊断的多层级工程化工具体系
android·ios·小程序·https·uni-app·iphone·webview
Winter_Sun灬12 小时前
CentOS 7 编译安卓 arm64-v8a 版 OpenSSL 动态库(.so)
android·linux·centos
柯南二号12 小时前
【大前端】【Android】用 Python 脚本模拟点击 Android APP —— 全面技术指南
android·前端·python