这一节了解一下derivedStateOf,它用于创建一个派生状态。派生状态是一种特殊的状态,它的值是根据其他状态计算得出的。当依赖的状态发生变化时,派生状态会自动重新计算。使用 derivedStateOf 的主要目的是优化重组,避免不必要的重组,提高 Compose 应用的性能。因为它可以缓存计算结果,只有当依赖的状态改变时才会重新计算,而不是每次重组都重新计算。
栗子:
@Composable
fun DerivedStateExample() {
// 定义两个可变状态
var num1 by remember { mutableStateOf(1) }
var num2 by remember { mutableStateOf(2) }
// 创建派生状态,其值为 num1 和 num2 的和
val sum by derivedStateOf {
num1 + num2
}
// 简单的 UI 显示状态值
Text(text = "num1: $num1, num2: $num2, sum: $sum")
// 提供按钮来改变 num1 和 num2 的值
Button(onClick = { num1++ }) {
Text("Increment num1")
}
Button(onClick = { num2++ }) {
Text("Increment num2")
}
}
分析:在这个例子中,sum 是一个派生状态,它的值依赖于 num1 和 num2。当 num1 或 num2 发生变化时,sum 会自动重新计算。
@SuppressLint("UnrememberedMutableState")
@Composable
fun ListDerivedStateExample() {
// 定义一个可变的列表状态
val items = remember { mutableStateListOf("Item 1", "Item 2", "Item 3") }
// 创建派生状态,计算列表的大小
val itemCount by derivedStateOf {
items.size
}
// 显示列表大小
Text(text = "Item count: $itemCount")
// 显示列表
LazyColumn {
items(items) { item ->
Text(text = item)
}
}
// 提供按钮来添加新项
Button(onClick = { items.add("New Item") }) {
Text("Add Item")
}
}
分析:itemCount 是一个派生状态,它的值依赖于 items 列表的大小。当列表中添加或删除项时,itemCount会自动重新计算。
注意:
1 尽管 derivedStateOf
能够优化重组性能,但过度使用会让代码变得复杂,降低代码的可读性和可维护性。只有在确实需要缓存计算结果以避免不必要的重组时,才使用它。例如,若只是简单的一次性计算,就无需使用 derivedStateOf
。
2 派生状态的生命周期和创建它的可组合函数的生命周期相关。当可组合函数不再被重组时,派生状态可能会被销毁。所以,要确保在合适的地方使用派生状态,防止在不需要的时候创建和销毁它们,以免造成额外的内存开销。
3 derivedStateOf 内部的计算逻辑应当简洁高效,避免进行复杂的计算或者耗时的操作。因为每次依赖状态改变时,计算逻辑都会被执行。若计算逻辑过于复杂,可能会影响应用的性能。