Compose 中的稳定性

Compose 将类型视为稳定或不稳定。如果某个类型是稳定的类型 不可变,或者 Compose 是否可以知道其值是否具有 在重组之间发生了变化如果 Compose 无法确定类型是否不稳定,请按以下步骤操作: 其值在重组后发生了变化。

Compose 使用可组合项参数的稳定性来确定它是否 可以在重组期间跳过可组合项:

  • 稳定的参数:如果可组合项具有未 Compose 会跳过它。
  • 参数不稳定:如果可组合项的参数不稳定,Compose 在重组组件的父项时始终会对其执行重组。

如果应用包含许多不必要的不稳定组件,Compose 会始终这些组件 重组时,可能会出现性能问题和其他问题。

本文档详细介绍了如何提高应用的稳定性以改进 性能和整体用户体验。

不可变对象

以下代码段演示了稳定性和 重组。

Contact 类是一个不可变的数据类。这是因为 形参是使用 val 关键字定义的基元。创建 Contact 的实例,则无法更改该对象属性的值。 如果您尝试这样做,则会创建一个新对象。

data class Contact(val name: String, val number: String)

ContactRow 可组合项有一个 Contact 类型的形参。

@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
   var selected by remember { mutableStateOf(false) }

   Row(modifier) {
      ContactDetails(contact)
      ToggleButton(selected, onToggled = { selected = !selected })
   }
}

考虑一下,当用户点击切换按钮和 selected 状态变化:

  1. Compose 会评估是否应重组 ContactRow 中的代码。
  2. 它发现 ContactDetails 的唯一参数是 Contact 类型。
  3. 由于 Contact 是一个不可变的数据类,因此 Compose 可确保 ContactDetails 的参数已更改。
  4. 因此,Compose 会跳过 ContactDetails,并且不会重组它。
  5. 另一方面,ToggleButton 的参数已更改, Compose 会重组该组件。

可变对象

虽然前面的示例使用的是不可变对象,但您可以创建一个 可变对象。请参考以下代码段:

data class Contact(var name: String, var number: String)

由于 Contact 的每个参数现在都是 var,因此类不再是不可变的。 如果其属性发生更改,Compose 不会感知。这是因为 Compose 仅跟踪对 Compose 状态对象的更改。

Compose 认为此类类不稳定。Compose 不会跳过重组 不稳定的类。因此,如果以这种方式定义 ContactContactRow 只要 selected 发生变化,前面的示例中便会重组。

在 Compose 中实现

考虑 Compose 究竟是如何实现的,虽然并不重要,但会很有帮助 确定在重组期间要跳过的函数。

当 Compose 编译器对代码运行时,它会标记每个函数和类型 。这些标记反映了 Compose 处理函数的方式, 类型。

函数

Compose 可以将函数标记为 skippablerestartable。请注意, 将函数标记为其中之一、两者或一个也不:

  • 可跳过:如果编译器将可组合项标记为可跳过,Compose 可以 如果它的所有参数都等于它们,则在重组期间会跳过它 先前的值。
  • 可重启:可重启的可组合项充当“作用域”其中 可以开始重组。换句话说,该函数可以是 条目,指明 Compose 可在什么之后开始重新执行代码以进行重组 状态更改

类型

Compose 将类型标记为不可变或稳定。每种类型都为 其他:

  • 不可变:如果某个类型的值已发生变化,Compose 会将其标记为不可变。 属性永远不能更改,并且所有方法都是引用透明的。
    • 请注意,所有基元类型都标记为不可变。这些国家/地区包括 StringIntFloat
  • Stable:表示在构造后其属性可以更改的类型。 如果这些属性在运行时发生变化,以及何时发生变化,Compose 会 这些更改

调试稳定性

如果您的应用要重组参数未更改的可组合项,请先 检查其定义,看看是否存在明显可变的参数。始终撰写 如果您传入具有 var 属性的类型或 val,则重组组件 属性。

如需详细了解如何在 Compose,请参阅调试稳定性指南。

解决稳定性问题

如需了解如何为 Compose 实现带来稳定性,请参阅 解决稳定性问题指南。

摘要

总体而言,您应注意以下几点:

  • 参数:Compose 会确定代码中每个参数的稳定性 可组合项,以确定在运行期间应跳过哪些可组合项 重组。
  • 立即修复:如果您发现自己的可组合项没有被跳过并且 导致性能问题,则应检查导致 不稳定,例如 var 参数。
  • 编译器报告:您可以使用编译器报告 确定推断出的类的稳定性。
  • 集合:Compose 始终认为集合类不稳定,例如 为List, SetMap。这是因为我们无法保证 不可更改。您可以改用 Kotlinx 不可变集合,或者 为类添加 @Immutable@Stable 注解。
  • 其他模块:Compose 始终认为其来源位置不稳定 不运行 Compose 编译器的模块。在界面中封装类 模型类。

深入阅读