比较 Compose 和 View 指标

Jetpack Compose 加速了 UI 开发并 改善了 Android 开发。但是,请考虑将 Compose 添加到现有应用中会如何影响应用的 APK 大小、构建和运行时性能等指标。

APK 大小和构建时间

本节将通过查看 Sunflower 示例应用(一个演示将基于 View 的应用迁移到 Compose 的最佳实践的应用)来了解对 APK 大小和构建时间的影响。

APK 大小

将库添加到您的项目会增加其 APK 大小。以下结果适用于每个项目的最小化发布版 APK,其中 启用了资源和代码压缩,使用 R8 全模式,并使用 APK 分析器 进行测量。

仅限 View 混合 View 和 Compose 仅限 Compose
下载大小 2,252 KB 3,034 KB 2,966 KB

首次将 Compose 添加到 Sunflower 时,APK 大小从 2,252 KB 增加到 3,034 KB,增加了 782 KB。生成的 APK 包含混合使用 View 和 Compose 的 UI 构建。由于向 Sunflower 添加了其他依赖项,因此会出现此增长。

相反,当 Sunflower 迁移到仅限 Compose 的应用时,APK 大小从 3,034 KB 降至 2,966 KB,减少了 68 KB。这种减少是由于删除了未使用的 View 依赖项(例如 AppCompatConstraintLayout)。

构建时间

添加 Compose 会增加应用的构建时间,因为 Compose 编译器会处理应用中的可组合项。以下结果是使用独立的 gradle-profiler 工具获得的,该工具执行多次构建,以便可以获得 Sunflower 调试构建持续时间的平均构建时间。

gradle-profiler --benchmark --project-dir . :app:assembleDebug
仅限 View 混合 View 和 Compose 仅限 Compose
平均构建时间 299.47 毫秒 399.09 毫秒 342.16 毫秒

首次将 Compose 添加到 Sunflower 时,平均构建时间从 299 毫秒增加到 399 毫秒,增加了 100 毫秒。此持续时间是由于 Compose 编译器执行其他任务以转换项目中定义的 Compose 代码。

相反,当 Sunflower 完成迁移到 Compose 时,平均构建时间下降到 342 毫秒,减少了 57 毫秒。这种减少可归因于几个因素,这些因素共同减少了构建时间,例如删除 数据绑定、迁移使用 kapt 到 KSP 的依赖项以及将多个依赖项更新到最新版本。

总结

采用 Compose 将有效增加应用的 APK 大小,并由于 Compose 代码的编译过程而增加应用的构建时间性能。但是,需要权衡这些权衡与 Compose 的优势,尤其是在采用 Compose 时围绕开发人员生产力提高方面。例如,Play 商店团队 发现,编写 UI 需要更少的代码,有时最多可减少 50%,从而提高代码的生产力和可维护性。

您可以在 为团队采用 Compose 中阅读更多案例研究。

运行时性能

本节涵盖与 Jetpack Compose 中运行时性能相关主题,以帮助了解 Jetpack Compose 与 View 系统的性能相比如何以及如何对其进行衡量。

智能重新组合

当 UI 的一部分无效时,Compose 会尝试仅重新组合需要更新的部分。在 可组合项的生命周期Jetpack Compose 阶段 文档中阅读有关此内容的更多信息。

基线配置文件

基线配置文件 是加速常见用户体验的绝佳方法。通过在您的应用中包含基线配置文件,可以通过避免解释和即时 (JIT) 编译包含代码路径的步骤,将代码执行速度从首次启动提高约 30%。

Jetpack Compose 库包含其自己的基线配置文件,并且在应用中使用 Compose 时,您会自动获得这些优化。但是,这些优化仅影响 Compose 库内的代码路径,因此我们建议您 向您的应用添加基线配置文件 以涵盖 Compose 之外的代码路径。

与 View 系统的比较

Jetpack Compose 对 View 系统进行了许多改进。这些改进在以下部分中进行了描述。

所有内容都扩展 View

每个在屏幕上绘制的 View(例如 TextViewButtonImageView)都需要内存分配、显式状态跟踪和各种回调以支持所有用例。此外,自定义 View 所有者需要实现显式逻辑以防止在不需要时重新绘制,例如重复数据处理。

Jetpack Compose 通过几种方式解决了这个问题。Compose 没有用于绘制视图的显式可更新对象。UI 元素是简单的可组合函数,其信息以可重放的方式写入组合中。这有助于将显式状态跟踪、内存分配和回调减少到仅需要这些功能的可组合项,而不是由给定 View 类型的所有扩展名都需要它们。

此外,Compose 提供了 智能重新组合,如果不需要进行更改,则重放先前绘制的结果。

多次布局传递

传统的 ViewGroups 在其 measure 和 layout API 中具有很强的表达能力,这使得它们容易出现多次布局传递。如果在视图层次结构中的特定嵌套点执行这些多次布局传递,则会导致指数级的工作量。

Jetpack Compose 通过其 API 合同为所有布局可组合项强制执行 单次布局传递。这使 Compose 可以有效地处理深层 UI 树。如果需要多次测量,Compose 具有 内在测量

View 启动性能

View 系统需要在首次显示特定布局时膨胀 XML 布局。在 Jetpack Compose 中节省了此成本,因为布局是用 Kotlin 编写的并像应用的其余部分一样进行编译。

基准测试 Compose

在 Jetpack Compose 1.0 中,应用在 debugrelease 模式下的性能存在显着差异。对于有代表性的计时,在分析应用时始终使用 release 构建而不是 debug

要检查 Jetpack Compose 代码的性能,可以使用 Jetpack Macrobenchmark 库。要了解如何在 Jetpack Compose 中使用它,请参阅 MacrobenchmarkSample 项目

Jetpack Compose 团队还使用 Macrobenchmark 来捕获可能发生的任何回归。例如,请参阅 惰性列的基准测试 及其 仪表板 以跟踪回归。

Compose 配置文件安装

由于 Jetpack Compose 是一个非捆绑库,因此它无法从 Zygote 中获益,Zygote 预加载了 View 系统的 UI 工具包类和可绘制对象。Jetpack Compose 1.0 利用配置文件安装用于发布版本。 配置文件安装程序 允许应用指定在安装时要提前 (AOT) 编译的关键代码。Compose 提供配置文件安装规则,可减少 Compose 应用的启动时间和卡顿。