ko2*_*2ic 2 android android-jetpack-compose compose-recomposition
This application counts up A when C is pressed. Since A is the only one that has changed, I expected the recomposition to be just that. But C is also recomposition.
Here is the code.
ViewModel exposes StateFlow.
class MainViewModel : ViewModel() {
private val _count: MutableStateFlow<Int> = MutableStateFlow(0)
val count: StateFlow<Int> = _count.asStateFlow()
fun increaseCount() {
_count.value++
}
}
Run Code Online (Sandbox Code Playgroud)
CCompose calls increaseCount().
@Composable
fun CountUpScreen(
modifier: Modifier = Modifier,
viewModel: MainViewModel = viewModel(),
) {
val count: Int by viewModel.count.collectAsState()
SideEffect { println("CountUpScreen") }
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
ACompose(
count = count
)
BCompose()
CCompose {
viewModel.increaseCount()
}
}
}
@Composable
private fun ACompose(count: Int) {
SideEffect { println("ACompose") }
Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = "$count"
)
}
}
@Composable
private fun BCompose() {
SideEffect { println("BCompose") }
Text(
text = "I am composable that will not be recompose"
)
}
@Composable
private fun CCompose(onClick: () -> Unit) {
SideEffect { println("CCompose") }
Button(onClick = {
onClick()
}) {
Icon(Icons.Outlined.Add, contentDescription = "+")
}
}
Run Code Online (Sandbox Code Playgroud)
The following are the results of the logs that were made to count up.
I/System.out: CountUpScreen
I/System.out: ACompose
I/System.out: CCompose
Run Code Online (Sandbox Code Playgroud)
Why is CCompose recomposed?
这里发生了一些事情。
首先,Compose 编译器不会自动记忆捕获不稳定类型的lambda 。您的 ViewModel 是一个不稳定的类,因此通过在 onClick lambda 中使用它来捕获它意味着您onClick将在每次重组时重新创建。
因为 lambda 正在重新创建,所以输入CCompose在重组过程中并不相等,因此CCompose会被重组。
这是 Compose 编译器当前的行为,但将来很可能会发生变化,因为我们知道这是一种常见情况,我们可以做得更好。
如果您想解决此问题,您可以自己记住 lambda。这可以通过在组合中记住它来完成,例如
val cComposeOnClick = remember(viewModel) { { viewModel.increaseCount() } }
CCompose(onClick = cComposeOnClick)
Run Code Online (Sandbox Code Playgroud)
或者更改您的 ViewModel 以使用 lambda 而不是increaseCount 函数。
class MyViewModel {
val increaseCount = { ... }
}
Run Code Online (Sandbox Code Playgroud)
或者您可以在技术上使用 @Stable 注释您的 ViewModel 类,但我可能不会推荐这样做,因为正确维护该稳定合同将非常困难。
执行其中任何一项都可以CCompose跳过。但我还想提一下,如果CCompose只是一个小的可组合项,那么 1 次额外的重组实际上可能不会对您的应用程序的性能产生太大影响,只有当它实际上导致您出现问题时,您才会应用这些修复程序。
稳定性是一个很大的话题,我建议阅读这篇文章以获取更多信息。
| 归档时间: |
|
| 查看次数: |
612 次 |
| 最近记录: |