提问人:thetwom 提问时间:8/31/2023 更新时间:9/1/2023 访问量:84
更新喷气背包中的局部变量组成和副作用
Updating local variables in jetpack compose and side effects
问:
阅读有关喷气背包撰写(在撰写中思考)的副作用,我找到了这个例子:
@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
var items = 0
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Column {
for (item in myList) {
Text("Item: $item")
items++ // Avoid! Side-effect of the column recomposing.
}
}
Text("Count: $items")
}
}
如本示例的上下文所述,这是不正确的,因为不允许修改局部变量。现在我想知道,什么是允许的,什么是不允许的。compose 如何知道它可以并行评估?如果将其移动到 -scope 中,是否允许?items
item in myList
var items
Column
更进一步,是否允许更新变量?我们可以做这样的事情吗:
class LongLastingClass() {
var someState = mutableStateOf(0)
private set
fun update(value: Int) {
someState = value
}
}
@Composable
fun ListWithUpdate(value: Int) {
val longLastingObject = remember{ LongLastingClass() }
longLastingObject.update(value)
...
}
还是必须转移到副作用之类的东西上?或者这个结构是一个问题,因为我们最好不要修改可组合项中的状态变量,所以需要副作用?update
答:
1赞
chuckj
9/1/2023
#1
暂时忽略它们,因为它们是内联函数并且很特殊,因此您永远不应该在 Compose 中编写依赖于可组合 lambda 何时执行的代码。它可能不会产生您期望的结果。Row
Column
如果将上述内容更改为
@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
var items = 0
A {
B {
for (item in myList) {
Text("Item: $item")
items++ // Avoid! Side-effect of the column recomposing.
}
}
Text("Count: $items")
}
}
仅当每个行调用始终调用调用其 lambda 时,此代码才有效,而调用调用其 lambda。如果 的 lambda 被调用并被跳过,则 的值将在 执行时。换言之,此代码仅在不跳过且传递给的 lambda 不跳过时才有效,无论何时执行。ListWithBug
A
B
A
B
items
0
Text("Count: $items")
B
B
ListWithBug
此代码错误不需要并行性,只需跳过即可。
这样就不用Compose来计数了。如果您将其更改为
@Composable
fun WorkingList(myList: List<String>) {
A {
B {
for (item in myList) {
Text("Item: $item")
}
}
Text("Count: ${myList.size}")
}
}
它产生相同的结果,而不依赖于何时或是否执行可组合的 lambda。
评论
0赞
thetwom
9/4/2023
这使事情变得更加清晰。因此,这意味着将 移动到 -scope(忽略它是一个内联函数)将使代码有效。第二个示例中描述的变量更新也是正确的代码。右?var items = 0
Column
0赞
chuckj
9/6/2023
代码可以工作,但我仍然不认为这个代码有效。一般来说,不要在可组合函数中使用 var 局部变量,因为它几乎从来都不是正确的,而且在它工作的情况下,对函数的任何更改都极有可能导致它将来中断。切勿使用组合来生成中间结果,因为这些结果可能无效,因为组合函数不能保证运行通常的序列。改为在视图模型中生成完整的结果,并使用组合来可视化这些结果。
0赞
thetwom
9/7/2023
谢谢。我理解状态逻辑应该保留在外面。归根结底,这更多的是为了理解。如果涉及到状态之间的动画转换,我想了解如何在可组合对象中更新状态很重要......
1赞
chuckj
9/8/2023
" ...了解如何更新可组合项中的状态非常重要“:不要更新可组合项中的状态。使用协程或其他机制来更新 compose 将响应的状态。
评论