gpt4 book ai didi

android - Jetpack Compose 智能重组

转载 作者:行者123 更新时间:2023-12-04 23:44:02 25 4
gpt4 key购买 nike

我正在做实验来理解重组和智能重组并制作了一个样本
enter image description here
对不起颜色,它们是用 Random.nextIn() 生成的,以直观地观察重组,设置颜色对重组没有影响,也尝试过不改变颜色。
gif中的内容由三部分组成
sample 1

@Composable
private fun Sample1() {

Column(
modifier = Modifier
.background(getRandomColor())
.fillMaxWidth()
.padding(4.dp)
) {
var counter by remember { mutableStateOf(0) }


Text("Sample1", color = getRandomColor())

Button(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = {
counter++
}) {
Text("Counter: $counter", color = getRandomColor())
}
}
}
我没有问题,因为智能合成按预期工作, Text在顶部没有读取 counter 中的更改所以重组只发生在 Text里面 Button .
sample 2
@Composable
private fun Sample2() {
Column(
modifier = Modifier.background(getRandomColor())
) {

var update1 by remember { mutableStateOf(0) }
var update2 by remember { mutableStateOf(0) }

println("ROOT")
Text("Sample2", color = getRandomColor())

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 4.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = {
update1++
},
shape = RoundedCornerShape(5.dp)
) {

println("🔥 Button1️")

Text(
text = "Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)

}

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 2.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = { update2++ },
shape = RoundedCornerShape(5.dp)
) {
println("🍏 Button 2️")

Text(
text = "Update2: $update2",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}

Column(
modifier = Modifier.background(getRandomColor())
) {

println("🚀 Inner Column")
var update3 by remember { mutableStateOf(0) }

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 2.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = { update3++ },
shape = RoundedCornerShape(5.dp)
) {

println("✅ Button 3️")
Text(
text = "Update2: $update2, Update3: $update3",
textAlign = TextAlign.Center,
color = getRandomColor()
)

}
}

Column() {
println("☕️ Bottom Column")
Text(
text = "Sample2",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}

}
}
它也可以按预期工作,每个 mutableState 只更新它们被观察到的范围。只有 Text观察 update2update3当这些 mutableStates 中的任何一个被更新时,就会发生变化。
sample 3
@Composable
private fun Sample3() {
Column(
modifier = Modifier.background(getRandomColor())
) {


var update1 by remember { mutableStateOf(0) }
var update2 by remember { mutableStateOf(0) }


println("ROOT")
Text("Sample3", color = getRandomColor())

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 4.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = {
update1++
},
shape = RoundedCornerShape(5.dp)
) {

println("🔥 Button1️")

Text(
text = "Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)

}

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 2.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = { update2++ },
shape = RoundedCornerShape(5.dp)
) {
println("🍏 Button 2️")

Text(
text = "Update2: $update2",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}

Column {

println("🚀 Inner Column")
var update3 by remember { mutableStateOf(0) }

Button(
modifier = Modifier
.padding(start = 8.dp, end = 8.dp, top = 2.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(backgroundColor = getRandomColor()),
onClick = { update3++ },
shape = RoundedCornerShape(5.dp)
) {

println("✅ Button 3️")
Text(
text = "Update2: $update2, Update3: $update3",
textAlign = TextAlign.Center,
color = getRandomColor()
)

}
}
// 🔥🔥 Reading update1 causes entire composable to recompose
Column(
modifier = Modifier.background(getRandomColor())
) {
println("☕️ Bottom Column")
Text(
text = "Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}
}
}
之间的唯一区别 sample 2 sample 3 Text底部正在读取 update1 mutableState ,这会导致整个可组合对象被重新组合。正如您在 gif 更改中看到的 update1重构或更改 Sample3 的整个颜色模式。
重组整个可组合的原因是什么?
        Column(
modifier = Modifier.background(getRandomColor())
) {
println("☕️ Bottom Column")
Text(
text = "Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}
}

最佳答案

让智能重组范围发挥关键作用。您可以查看 Vinay Gaba 的 What is “donut-hole skipping” in Jetpack Compose?文章。
Leland Richardson 在此 tweet 中解释作为

The part that is "donut hole skipping" is the fact that a new lambdabeing passed into a composable (ie Button) can recompose withoutrecompiling the rest of it. The fact that the lambda are recomposescopes are necessary for you to be able to do this, but notsufficient

In other words, composable lambda are "special" :)

We wanted to do this for a long time but thought it was toocomplicated until @chuckjaz had the brilliant realization that if thelambdas were state objects, and invokes were reads, then this isexactly the result


也可以查看其他关于智能重构的答案 here , 和 here .
https://dev.to/zachklipp/scoped-recomposition-jetpack-compose-what-happens-when-state-changes-l78
当一个状态被读取时,它会在最近的范围内触发重组。而作用域是一个没有用 inline 标记并返回 Unit 的函数。 Column、Row 和 Box 是内联函数,因此它们不会创建范围。
已创建 RandomColorColumn采取其他 Composables及其范围 content: @Composable () -> Unit
@Composable
fun RandomColorColumn(content: @Composable () -> Unit) {

Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(getRandomColor())
.padding(4.dp)
) {
content()
}
}
并更换
 Column(
modifier = Modifier.background(getRandomColor())
) {
println("☕️ Bottom Column")
Text(
text = "Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}
}
    RandomColorColumn() {

println("☕️ Bottom Column")
/*
🔥🔥 Observing update(mutableState) does NOT causes entire composable to recompose
*/
Text(
text = "🔥 Update1: $update1",
textAlign = TextAlign.Center,
color = getRandomColor()
)
}
}
只有这个范围按预期更新,我们有智能重组。
enter image description here
是什么原因导致 Text ,或任何可组合的,在 Column没有范围,因此当 mutableState 值更改时被重新组合是 Column内联 函数签名中的关键字。
@Composable
inline fun Column(
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable ColumnScope.() -> Unit
) {
val measurePolicy = columnMeasurePolicy(verticalArrangement, horizontalAlignment)
Layout(
content = { ColumnScopeInstance.content() },
measurePolicy = measurePolicy,
modifier = modifier
)
}
如果添加 内联 RandomColorColumn函数签名你会看到它导致 整体可组合重组 .
撰写使用 call sites定义为

The call site is the source code location in which a composable iscalled. This influences its place in Composition, and therefore, theUI tree.

If during a recomposition a composable calls different composablesthan it did during the previous composition, Compose will identifywhich composables were called or not called and for the composablesthat were called in both compositions, Compose will avoid recomposingthem if their inputs haven't changed.


考虑以下示例:
@Composable
fun LoginScreen(showError: Boolean) {
if (showError) {
LoginError()
}
LoginInput() // This call site affects where LoginInput is placed in Composition
}

@Composable
fun LoginInput() { /* ... */ }
Composable 函数的调用站点会影响智能重构,并且具有 内联 Composable 中的关键字将其子 Composable 调用站点设置为同一级别,而不是低于一级。
对这里感兴趣的人是 github repo播放/测试重组

关于android - Jetpack Compose 智能重组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70257459/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com