Ji *_*bin 51 android android-jetpack-compose compose-recomposition
在研究 Jetpack Compose 示例项目时,我看到了@Stable注释@Immutable。我一直在浏览Android 文档和GitHub关于这些注释的信息,但我不明白。
据我了解,如果使用@Immutable,即使状态改变,也不应该发生重组。然而,作为测试的结果,重组仍在继续。
@StableJetpack Compose 中注释的具体作用是什么@Immutable?
I'm*_*gon 74
定义
@Immutable是一个注释,告诉 Compose 编译器该对象对于优化来说是不可变的,因此如果不使用它,可能会触发不必要的重新组合。
@Stable是另一个注释,告诉 Compose 编译器这个对象可能会改变,但是当它改变时,Compose 运行时会收到通知。
如果您读到这里可能没有意义。所以更多解释...
Compose 指标报告
当您生成 compose 指标报告(https://github.com/androidx/androidx/blob/08c6116/compose/compiler/design/compiler-metrics.md)时,它会将事物标记为stable或unstable,对于unstable对象,Compose 编译器不能告诉对象是否被修改,因此无论如何它都必须触发重组。以下是该报告的两个片段:
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>
)
Run Code Online (Sandbox Code Playgroud)
需要可跳过!
在 的情况下SomeClass1,它被标记为skippable,因为它的所有参数都被标记为stable。对于SomeClass2,它不会被标记为skippable,因为它有一个list属性unstable。
当它被标记为 时skippable,这是一件好事,因为 Compose 编译器可以尽可能跳过重组,并且它更加优化。
什么时候会无法标记为可跳过?
通常 compose 编译器足够聪明,可以推断出什么是stable以及什么是unstable。在组合编译器无法判断可变对象稳定性的情况下,例如包含var属性的类。
class SomeViewState {
var isLoading: Boolean
}
Run Code Online (Sandbox Code Playgroud)
另一种无法确定稳定性的情况是像 之类的类Collection,List因为即使接口List看起来不可变,它实际上也可以是一个可变列表。例子:
data class SomeViewState {
val list: List<String>
}
@Composable
fun ShowSomething(data: SomeViewState) {
}
Run Code Online (Sandbox Code Playgroud)
尽管上面的 Composable 接受SomeViewState其所有属性所在的位置val,但它仍然是unstable。你可能想知道为什么?这是因为在使用方面,您实际上可以将它与 a 一起使用MutableList,如下所示:
ShowSomething(SomeViewState(mutableListOf()))
Run Code Online (Sandbox Code Playgroud)
因此,编译器必须将其标记为unstable.
所以在这样的情况下,我们想要实现的就是stable重新制作它们,从而优化它们。
@Stable 和 @Immutable
有两种方法可以stable重新制作,分别是使用@Stable和@Immutable。
使用@Stable,如上所述,意味着该值可以更改,但是当它确实更改时,我们必须通知 Compose 编译器。做到这一点的方法是通过使用mutableStateOf():
@Stable
class SomeViewState {
var isLoading by mutableStateOf(false)
}
Run Code Online (Sandbox Code Playgroud)
使用@Immutable,意味着当您传递到可组合项时,您将始终创建数据的新副本,换句话说,您承诺您的数据是不可变的。从上面的例子来看:
@Immutable
data class SomeViewState {
val list: List<String>
}
@Composable
fun ShowSomething(data: SomeViewState) {
}
Run Code Online (Sandbox Code Playgroud)
在使用进行注释后@Immutable,您应该确保创建一个新列表,而不是直接改变列表。
示例:
class ViewModel {
val state: SomeViewState = SomeViewState(listOf())
fun removeLastItem() {
val newList = state.list.toMutableList().apply {
removeLast()
}
state = state.copy(
list = newList
)
}
}
Run Code Online (Sandbox Code Playgroud)
示例不要:
class ViewModel {
val state: SomeViewState = SomeViewState(mutableListOf())
fun removeLastItem() {
state.list.removeLast() // <=== you violate your promise of @Immutable!
}
}
Run Code Online (Sandbox Code Playgroud)
为了更深入的了解,您可以阅读以下链接:
Gab*_*tti 43
编译器对两者的处理方式相同,但是
@Immutable是一种价值永远不会改变的承诺。@Stable是一个承诺,即该值是可观察的,如果它确实发生变化,侦听器会收到通知。| 归档时间: |
|
| 查看次数: |
16385 次 |
| 最近记录: |