发布于 2022-11-15 06:52:10
定义
@Immutable是一个注释,用来告诉Compose这个对象是不可变的优化对象,所以如果不使用它,可能会触发不必要的重新组合。
@Stable是另一个注释,用于告诉Compose编译器该对象可能会更改,但当它更改时,将通知Compose运行时。
如果你读到这里,这可能是没有意义的。所以更多的解释..。
组合度量报告
当生成组合度量报告(https://github.com/androidx/androidx/blob/08c6116/compose/compiler/design/compiler-metrics.md)时,它会将事情标记为stable或unstable,对于unstable对象,组合编译器无法判断对象是否被修改,因此它必须不加考虑地触发重新组合。下面是报告的两个片段:
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SomeClass1(
stable modifier: Modifier? = @static Companion
)
restartable scheme("[androidx.compose.ui.UiComposable]") fun SomeClass2(
stable modifier: Modifier? = @static Companion
stable title: String
unstable list: List<User>
stable onClicked: Function1<User>, Unit>
)需要可跳过的!
在SomeClass1的例子中,它被标记为skippable,因为它的所有参数都被标记为stable。对于SomeClass2,它不会被标记为skippable,因为它有一个属性list,即unstable。
当它被标记为skippable时,这是一件好事,因为Compose编译器可以跳过任何可能的重新组合,并且它是更优化的。
什么时候不能被标记为可跳?
通常compose编译器足够聪明,可以推断什么是stable,什么是unstable。在组合编译器无法判断稳定性是可变对象的情况下,例如包含var属性的类。
class SomeViewState {
var isLoading: Boolean
}另一种无法决定稳定性的情况是Collection类,如List,因为即使接口是List (看起来是不可变的),它实际上也可以是一个可变列表。示例:
data class SomeViewState {
val list: List<String>
}
@Composable
fun ShowSomething(data: SomeViewState) {
}尽管上面的Composable接受SomeViewState,它的所有属性都是val,但它仍然是unstable。你可能想知道为什么?这是因为在使用方面,您实际上可以在MutableList中使用它,如下所示:
ShowSomething(SomeViewState(mutableListOf()))因此,编译器必须将其标记为unstable。
因此,在这种情况下,我们想要实现的是让他们再次stable,所以他们是优化的。
@稳定和@不变的
有两种方法可以让它再次成为stable,它们使用@Stable和@Immutable。
使用@Stable,正如上面提到的,它意味着值可以更改,但是当它发生更改时,我们必须通知Compose编译器。这样做的方法是通过使用mutableStateOf()
@Stable
class SomeViewState {
var someFlag by mutableStateOf(false)
}使用@Immutable,这意味着当您将数据传递到Composable中时,您将始终创建一个新的数据副本,在其他病房中,您承诺您的数据是不可变的。从上面的例子来看:
@Immutable
data class SomeViewState {
val list: List<String>
}
@Composable
fun ShowSomething(data: SomeViewState) {
}在用@Immutable进行注释之后,在您的使用端,您应该确保创建一个新列表,而不是直接更改列表。
例如:
class ViewModel {
val state: SomeViewState = SomeViewState(listOf())
fun removeLastItem() {
val newList = state.list.toMutableList().apply {
removeLast()
}
state = state.copy(
list = newList
)
}
}例:不要:
class ViewModel {
val state: SomeViewState = SomeViewState(mutableListOf())
fun removeLastItem() {
state.list.removeLast() // <=== you violate your promise of @Immutable!
}
}为了加深理解,您可以阅读以下链接:
https://stackoverflow.com/questions/68575936
复制相似问题