Jetpack Compose 性能

Jetpack Compose 旨在提供开箱即用的卓越性能。本页介绍了如何编写和配置应用以实现更好的性能,并展示了一些应避免使用的模式。

您可能需要先熟悉 Compose 编程思想中的核心 Compose 概念。

正确配置您的应用

如果您的应用性能不佳,则可能存在配置问题。建议您首先检查以下配置选项。

在发布模式下构建并使用 R8

如果您遇到性能问题,请尝试在发布模式下运行应用。调试模式对于发现许多问题非常有用,但它会产生大量的性能开销,并且可能很难发现其他可能会影响性能的代码问题。我们还建议您使用 R8 编译器启用优化和缩减功能,以确保高性能且高效的发布 build。

使用基准配置文件

基准配置文件可以避免对包含的代码路径执行解译和即时 (JIT) 编译步骤,从而让代码执行速度从首次启动开始提高约 30%。通过在应用或库中分发基准配置文件,Android 运行时 (ART) 可以通过预先 (AOT) 编译来优化包含的代码路径,从而针对每次新应用安装和每次应用更新提升性能。这种配置文件引导的优化 (PGO) 可让应用优化启动、减少互动卡顿,并提高整体的运行时性能,从而让用户从首次启动开始便获得更好的使用体验。

Compose 以库的形式分发,而不是作为 Android 平台的一部分分发。此方法可让 Compose 团队经常更新 Compose,并支持较低的 Android 版本。不过,以库形式分发 Compose 会产生费用。Android 平台代码已编译并安装到设备上。不过,在应用启动时需要加载库,并在需要相应功能时解释 JIT。这可能会导致应用在启动时以及首次使用库功能时减慢。

您可以通过定义基准配置文件来提高性能。这些配置文件定义了关键用户历程所需的类和方法,并与应用的 APK 或 AAB 文件一起分发。在应用安装期间,ART 会编译此关键代码 AOT,使其在应用启动时可供使用。

定义良好的基准配置文件并不总是简单明了,因此,Compose 默认自带了一个基准配置文件。您无需执行任何操作即可看到这项优势。不过,Compose 附带的基准配置文件仅包含针对 Compose 库中代码的优化。为了获得最佳优化效果,最好也为您的应用创建基准配置文件,该配置文件使用 Macrobenchmark 涵盖关键用户历程。定义自己的配置文件时,您必须测试配置文件以验证它是否有所帮助。为实现此目的,一种好方法是为您的应用编写 Macrobenchmark 测试,并在编写和修改基准配置文件时查看测试结果。如需查看如何为 Compose 界面编写 Macrobenchmark 测试的示例,请参阅 Macrobenchmark Compose 示例

如需详细了解发布模式、R8 和基准配置文件的影响,请参阅博文为什么应始终在发布版本中测试 Compose 性能?

Compose 的三个阶段对性能的影响

Jetpack Compose 阶段中所述,当 Compose 更新帧时,它会经历三个阶段:

  • 组合:Compose 确定要显示的内容。它会运行可组合函数并构建界面树。
  • 布局:Compose 确定界面树中每个元素的大小和位置。
  • 绘制:Compose 实际渲染各个界面元素。

Compose 可以智能地跳过其中任何不需要的阶段。例如,假设单个图形元素在尺寸相同的两个图标之间切换。由于此元素不会更改大小,并且不会添加或移除界面树的任何元素,因此 Compose 可以跳过组合和布局阶段并重新绘制这一个元素。

但是,一些编码错误可能会导致 Compose 更加难以确定可以安全地跳过哪些阶段。如果您有任何疑问,Compose 会运行所有三个阶段,这可能会降低界面的速度。因此,许多性能最佳实践都是帮助 Compose 跳过不需要的阶段。

总体而言,您需要遵循几项可以提高性能的宽泛原则:

  • 尽可能将计算移出可组合函数。 每当界面发生变化时,可能都需要重新运行可组合函数。您放置在可组合项中的任何代码都会重新执行,可能是针对动画的每一帧。将可组合项的代码限制为仅包含构建界面所需的代码。

  • 尽可能延后读取状态。通过将状态读取移至可组合子项或后续阶段,您可以最大限度地减少重组或完全跳过组合阶段。为此,您可以传递 lambda 函数(而不是状态值)以适应频繁变化的状态,并在传入频繁变化的状态时优先使用基于 lambda 的修饰符。您可以在尽可能延后读取部分查看此方法的示例。