比较 Compose 指标和 View 指标

Jetpack Compose 可加快界面开发并改进 Android 开发。不过,请考虑将 Compose 添加到现有应用会对应用的 APK 大小、构建和运行时性能等指标有何影响。

APK 大小和构建时间

本部分将通过 Sunflower 示例应用来了解对 APK 大小和构建时间的影响。该应用演示了将基于 View 的应用迁移到 Compose 的最佳实践。

APK 大小

将库添加到项目中会增加其 APK 大小。以下结果针对的是在启用了资源和代码缩减且使用 R8 完整模式的各项目的缩减版 APK 中,使用 APK 分析器进行衡量的。

仅限视图 混合 View 和 Compose 只写 Compose
下载大小 2,252 KB 3,034 KB 2966 KB

首次将 Compose 添加到 Sunflower 时,APK 大小从 2,252 KB 增加到 3,034 KB,增加了 782 KB。生成的 APK 由混合了 View 和 Compose 的界面 build 组成。由于向 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 和 Compose 只写 Compose
平均构建时间 299.47 毫秒 399.09 毫秒 342.16 毫秒

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

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

总结

由于 Compose 代码的编译过程,采用 Compose 将有效增加应用的 APK 大小,还会提高应用的构建时性能。不过,您需要权衡 Compose 的优势,特别是在采用 Compose 时开发者工作效率的提升方面,需要权衡这些利弊。例如,Play 商店团队发现编写界面所需的代码要少得多,有时需要高达 50%,从而提高了代码的工作效率和可维护性。

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

运行时性能

本部分介绍了与 Jetpack Compose 中的运行时性能相关的主题,以帮助您了解 Jetpack Compose 与 View 系统性能的对比情况,以及衡量方法。

智能重组

当界面的某些部分无效时,Compose 会尝试仅重组需要更新的部分。如需了解详情,请参阅可组合项的生命周期Jetpack Compose 阶段文档。

基准配置文件

基准配置文件是加快常见用户体验历程的理想方式。在应用中添加基准配置文件可以避免对包含的代码路径执行解译和即时 (JIT) 编译步骤,从而让代码执行速度从首次启动开始提高约 30%。

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

与 View 系统比较

与 View 系统相比,Jetpack Compose 提供了许多改进。以下各部分介绍了这些改进。

对 View 进行了全方位扩展

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

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

此外,Compose 提供了智能重组功能,如果您不需要进行更改,系统会重放之前绘制的结果。

多次布局传递

传统的 ViewGroup 在其测量和布局 API 方面具有很多表现力,因此容易出现多次布局传递。如果在视图层次结构中的特定嵌套点进行了多次布局传递,可能会导致工作量呈指数级增长。

Jetpack Compose 通过其 API 协定对所有布局可组合项强制执行单次布局传递。这样,Compose 就可以高效地处理较深的界面树。如果需要多次测量,Compose 可使用固有特性测量

View 启动性能

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

对 Compose 进行基准测试

在 Jetpack Compose 1.0 中,应用在 debugrelease 模式下的性能存在显著差异。为使得出的时间结果具有代表性,在对应用进行性能分析时,请始终使用 release build(而非 debug)。

如需查看 Jetpack Compose 代码的性能,您可以使用 Jetpack Macrobenchmark 库。如需了解如何将其与 Jetpack Compose 搭配使用,请参阅 MacrobenchmarkSample 项目

Jetpack Compose 团队还使用 Macrobenchmark 来捕获可能发生的任何回归问题。例如,请参阅延迟列的基准及其信息中心,以跟踪回归情况。

Compose 配置文件安装

由于 Jetpack Compose 是一个未捆绑库,因此它无法从预加载 View 系统的界面工具包类和可绘制对象的 Zygote 中受益。Jetpack Compose 1.0 利用配置文件安装进行发布 build。配置文件安装程序可让应用指定要在安装时进行预先 (AOT) 编译的关键代码。Compose 随附配置文件安装规则,可减少 Compose 应用的启动时间和卡顿。