比较 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 提供了智能重新组合,如果您不需要进行更改,则会重放先前绘制的结果。

多次布局传递

传统的 ViewGroup 在其测量和布局 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 应用的启动时间和卡顿。