Compose 性能

Jetpack Compose 旨在提供开箱即用的卓越性能。本页介绍了如何编写和配置应用以实现最佳性能,并指出了一些需要避免的模式。

在阅读本文之前,建议先熟悉 Compose 编程思想中的核心 Compose 概念。

正确配置您的应用

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

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

如果遇到性能问题,请务必尝试在发布模式下运行应用。调试模式有助于发现大量问题,但是会产生严重的性能开销,而且可能会难以发现其他可能影响性能的代码问题。您还应使用 R8 编译器从应用中移除不必要的代码。默认情况下,在发布模式下构建时会自动使用 R8 编译器。

使用基准配置文件

Compose 以库的形式分发,而不是作为 Android 平台的一部分分发。这种方式让我们能够经常更新 Compose,并且支持旧版 Android。然而,将 Compose 作为库分发会产生性能开销。Android 平台代码已完成编译并安装到设备上。另一方面,您需要在应用启动时加载库,并在需要功能时即时对库进行解释。这样一来,应用在启动时以及每次首次使用一个库功能时就会变得很慢。

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

要定义一个良好的基准配置文件并不容易,因而此 Compose 随带了一个默认的基准配置文件。您无需执行任何操作即可直接使用该配置文件。但是,如果您选择定义自己的配置文件,则可能会生成一个无法实际提升应用性能的配置文件。您应当测试该配置文件并验证它是否有效。为此,建议为您的应用编写一些 Macrobenchmark 测试,并根据测试结果来编写和修改基准配置文件。如需查看如何为 Compose 界面编写 Macrobenchmark 测试的示例,请参阅 Macrobenchmark Compose 示例

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

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

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

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

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

但是,一些编码错误可能会导致 Compose 更加难以确定可以安全地跳过哪些阶段。如果存在任何疑虑,Compose 最终会运行所有三个阶段,而这可能会导致界面运行速度变慢。因此,许多提升性能的最佳做法都侧重于帮助 Compose 跳过不需要的阶段。

总体而言,应当遵循一些可提升性能的基本原则。

首先,尽可能从可组合函数中移除计算。每当界面发生变化时,都可能需要重新运行可组合函数;可能对于动画的每一帧,都会重新执行您在可组合函数中放置的所有代码。因此,您应当仅在可组合函数中放置构建界面实际所需的代码。

其次,尽可能延后读取状态。通过将状态读取移至可组合子项或后续阶段,您可以尽可能减少重组或完全跳过组合阶段。为此,您可以传递 lambda 函数(而不是状态值)来表示经常更改的状态,并在传入经常更改的状态时优先使用基于 lambda 的修饰符。您可以在尽可能延后读取部分查看此技巧的示例。