如果您遇到由不必要或过度重组导致的性能问题,应调试应用的稳定性。本指南概述了几种调试方法。
布局检查器
Android Studio 中的布局检查器可让您查看应用中哪些可组合项正在重组。它会显示 Compose 重组或跳过组件的次数。
Compose 编译器报告
Compose 编译器可以输出其稳定性推断结果以供检查。使用此输出,您可以确定哪些可组合项是可跳过的,哪些不是。以下小节总结了如何使用这些报告,但如需了解更多详细信息,请参阅技术文档。
设置
Compose 编译器报告默认情况下未启用。您可以使用编译器标志激活它们。确切的设置因项目而异,但对于使用Compose 编译器 Gradle 插件的项目,您可以在每个模块的 build.gradle
文件中添加以下内容。
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
现在,构建项目时将生成 Compose 编译器报告。
示例输出
的 reportsDestination
会输出三个文件。以下是 JetSnack 的示例输出。
<modulename>-classes.txt
: 关于此模块中类稳定性的报告。示例。<modulename>-composables.txt
: 关于模块中可组合项的可重启性和可跳过性的报告。示例。<modulename>-composables.csv
: 可组合项报告的CSV
版本,您可以将其导入电子表格或使用脚本进行处理。示例
可组合项报告
的 composables.txt
文件详细说明了给定模块中的每个可组合函数,包括其参数的稳定性,以及它们是否可重启或可跳过。以下是来自 JetSnack 的一个假设示例
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
stable snackCollection: SnackCollection
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
stable index: Int = @static 0
stable highlight: Boolean = @static true
)
这个 SnackCollection
可组合项是完全可重启、可跳过且稳定的。这通常是优选的,但并非强制要求。
另一方面,我们来看另一个示例。
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
unstable snacks: List<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
这个 HighlightedSnacks
可组合项是不可跳过的。Compose 在重组期间从不跳过它。即使它的任何参数都没有改变,也会发生这种情况。原因是 不稳定
的参数 snacks
。
类报告
文件 classes.txt
包含给定模块中类的类似报告。以下代码段是类 Snack
的输出
unstable class Snack {
stable val id: Long
stable val name: String
stable val imageUrl: String
stable val price: Long
stable val tagline: String
unstable val tags: Set<String>
<runtime stability> = Unstable
}
供参考,以下是 Snack
的定义
data class Snack(
val id: Long,
val name: String,
val imageUrl: String,
val price: Long,
val tagline: String = "",
val tags: Set<String> = emptySet()
)
Compose 编译器已将 Snack
标记为不稳定。这是因为 tags
参数的类型是 Set<String>
。这是一种不可变类型,因为它不是 MutableSet
。但是,诸如 Set、List
和 Map
等标准集合类最终都是接口。因此,底层实现可能仍然是可变的。
例如,您可以编写 val set: Set<String> = mutableSetOf("foo")
。该变量是常量,其声明类型不可变,但其实现仍然可变。Compose 编译器无法确定此类的不可变性,因为它只看到声明类型。因此,它将 tags
标记为不稳定。