前言
上一章我们讲解了 Jetpack Compose -> mutableStateOf 状态机制的背后秘密 本章我们讲解下重组的性能风险以及怎么优化;
重组的性能风险
前面我们一直在讲重组(ReCompose) 的过程,在使用 mutableStateOf() 以及对于 List 和 Map 在使用 mutatbleStateListOf()、mutableStateMapOf() 也能监听到内部状态变化,如果对于 List 和 Map 使用的是 mutableStateOf() 只能触发这个对象变化的监听;
重组其实分为:触发重组和重组,这是两个过程,触发重组是某个变量发生改变之后,Compose 去把已经组合好的那些部分重新的 Compose 一次,这个所谓的组合好的部分就是之前说的组合过程的结果;也就是那个稍后被拿去组合、测量、绘制的结果,它在相关的变量改变之后,是需要重新组合过程,重新生成结果的;
触发重组,就是 ReCompose Scope 重组范围;重组是在下一帧的时候去调用这些失效了的 compose 代码,来重新生成组合的过程;
因为 Column 函数是一个内联函数,所以 Column 函数在编译后会被抹除掉,也就是说,如果我们在使用下面的逻辑的时候
private var number by mutableStateOf(1)
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Android_VMTheme {
Surface {
println("Recompose 测试范围1")
Column {
println("Recompose 测试范围2")
Text(text = "当前数值是: $number", modifier = Modifier.clickable {
number ++
})
}
}
}
}
}
Column 会被抹除掉,而是直接将 Text 放到那里,也就是说如果发生了 ReCompose 的时候,是会把 Column 前后范围内的都会触发 Recompose;
也就是说当我们点击 Text 触发 number++ 的时候,会再一次打印 “Recompose 测试范围1” 和 “Recompose 测试范围2”;
这其实就是重组的性能风险;一个小的改动,触发了大面积的 ReCompose,这就造成了计算资源浪费;
我们来继续验证下这个结论,假设我们有下面这样的一段代码
private var number by mutableStateOf(1)
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Android_VMTheme {
Surface {
println("Recompose 测试范围1")
Column {
testPerformance()
println("Recompose 测试范围2")
Text(text = "当前数值是: $number", modifier = Modifier.clickable {
number ++
})
}
}
}
}
}
@Composable
fun testPerformance() {
println(&