Skip to content

性能优化 (Performance)

源:Compose 性能最佳实践

Compose 的性能核心在于智能跳过 (Smart Recomposition)。如果你的 App 卡顿,通常是因为 Compose 无法确定参数是否发生变化,导致进行了不必要的重组。

1. 稳定性 (Stability)

Compose 编译器会将参数类型标记为“稳定”或“不稳定”。

  • 稳定 (Stable): Compose 知道该类型何时发生变化(例如 String, Int, data class with val)。
  • 不稳定 (Unstable): Compose 无法确定(例如 List, Map, 带有 var 属性的普通类)。

陷阱

如果 Composable 的参数包含 List<T>(这是接口,被视为不稳定),即使列表内容没变,Compose 每次也会重组该函数。

解决方案 A: 使用不可变集合

使用 Kotlinx Immutable Collections 库。

kotlin
// build.gradle
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7")

// 使用 PersistentList 替代 List
@Composable
fun ItemList(items: PersistentList<String>) { ... }

解决方案 B: 强跳过模式 (Strong Skipping)

从 Compose Compiler 1.5.4+ 开始,支持强跳过模式。它允许跳过参数不稳定的 Composable(通过比较实例引用)。

在 Kotlin 2.0 中,强跳过模式默认开启。

解决方案 C: @Stable / @Immutable 注解

手动告诉编译器:“相信我,这个类是稳定的”。

kotlin
@Stable
data class UiState(
    val items: List<String> // 普通 List 默认是不稳定的
)

2. defer read (推迟读取)

尽可能推迟状态的读取时机,使其在 Layout 或 Draw 阶段读取,而不是 Composition 阶段。

kotlin
// 每次 scroll 变化,都会触发 Composition 阶段重组
val scroll = scrollState.value
Box(Modifier.offset(y = scroll.dp))
kotlin
// 使用 Lambda,在 Layout 阶段才读取 scroll
// Composition 阶段不会因 scroll 变化而重组
Box(Modifier.offset { IntOffset(0, scrollState.value) })

3. 发布构建 (Release Build)

切勿在 Debug 模式下衡量性能!

Compose 在 Debug 模式下包含大量断言和调试代码,性能远低于 Release 模式。并且 R8 (ProGuard) 能够大幅优化 Compose 运行时的代码。

检查重组

在 Android Studio 中,启用 Layout Inspector,可以查看每个 Composable 的重组次数和跳过次数。这对于排查性能瓶颈至关重要。