我试图帮助某人解决这个问题
snapshotFlow
然后我们都很想知道这个州问题。正如我们所知 snapshotFlow
将帮助我们获得流状态值。
问题
val (number1, setNumber1) = remember {
mutableStateOf(0)
}
我们已经像上面的代码一样使用了这种状态。为了设置该值,我们使用了另一种方法。但由于某种原因,这个
snapshotFlow
不起作用,并且在 LaunchedEffect
中我们无法收集这些值。但后来尝试了这样。
val number2 = remember {
mutableStateOf(0)
}
这按预期工作。 那么可能是什么问题呢。当我们更改这些值时,
number1Flow
不会收集这些值,但 number2Flow
可以工作。
我们错过了什么,请告诉我们。
还有完整的代码。
@Composable
fun Sample() {
val (number1, setNumber1) = remember {
mutableStateOf(0)
}
val number2 = remember {
mutableStateOf(0)
}
LaunchedEffect(key1 = true) {
snapshotFlow {
number1
}.collect {
Log.v("number1Flow", it.toString())
}
}
LaunchedEffect(key1 = true) {
snapshotFlow {
number2.value
}.collect {
Log.v("number2Flow", it.toString())
}
}
Text(
text = "number1= $number1",
)
Text(
text = "number2= ${number2.value}",
)
Button(onClick = {
setNumber1(number1 + 1)
number2.value += 1
}) {
Text(
text = "increase the value",
)
}
}
SnapshotFlow 的工作原理与重组类似 - 它跟踪
State.value
的读取以了解何时发出。因此,要使 snapshotFlow
工作,必须在 snapshotFlow {}
块内部读取该值,这在第一种情况下不会发生。在第二种情况下,当您执行以下操作时,会在块内部读取值(这是显而易见的)
val number by remember { mutableStateOf(0) }
LaunchedEffect(Unit) { snapshotFlow { number } }
值也会在块内部读取,尽管由于委托的原因它不是直接可见的。但第一种情况与这样做是一样的:
val number = remember { mutableStateOf(0) }
val numberValue = number.value
LaunchedEffect(Unit) { snapshotFlow { numberValue } }
这里,该值是在
snapshotFlow
块之外读取的,这意味着它不知道要跟踪哪些更改。
这意味着一旦你使用解构声明来获取值和setValue,就不可能从中创建
snapshotFlow
。唯一的方法就是保留 State
:
val numberState = remember { mutableStateOf(0) }
val (number, setNumber) = numberState
LaunchedEffect(Unit) { snapshotFlow { numberState.value } }
您正在使用
创建一个新的
Flow
val number1Flow = snapshotFlow {
number1
}
在每次重新组合时,您收集的组合就是最初分配的组合。如果您记录
number1Flow
或 number2Flow
实例,您将看到在每个按钮上单击都会创建新实例。
您可以在 LaunchedEffect 中创建 Flow 并使用
收集相同的 FlowLaunchedEffect(key1 = true) {
snapshotFlow {
number2.value
}.collect {
}
}
请看一下这三个示例,其中代码块在可组合项下执行:
val x = remember { mutableStateOf("X1") }
LaunchedEffect(Unit) {
snapshotFlow { x.value }.collect { println("x collected: $it") }
}
LaunchedEffect(Unit){
delay(300)
x.value = "X2"
println("x.value: ${x.value}")
}
//Outputs:
// x collected: X1
// x.value: X2
// x collected: X2
var y by remember { mutableStateOf("Y1") }
LaunchedEffect(Unit) {
snapshotFlow { y }.collect { println("y collected: $it") }
}
LaunchedEffect(Unit) {
delay(300)
y = "Y2"
println("y: $y")
}
//Outputs:
// y collected: Y1
// y: Y2
// y collected: Y2
val (zValue, zSetter) = remember { mutableStateOf("Z1") }
LaunchedEffect(Unit) {
snapshotFlow { zValue }.collect { println("zValue collected: $it") }
}
LaunchedEffect(Unit) {
delay(300)
zSetter("Z2")
println("zValue: $zValue")
}
//Outputs:
// zValue collected: Z1
// zValue: Z1
请注意,示例 1 和 2 的行为相同,而示例 3 面临与您的问题相同的问题,其中值
zValue
未更新。
这个问题的关键是 1. MutableState
上
解构声明的行为,以及 2.
snapshotFlow{ ... }
函数的行为。
component1
的 MutableState
是其解构时的 value
。SnapshotFlow
成为 emit
一个新值,必须在 value
块内访问 State
的 snapshotFlow{ ... }
属性。因此,要解决该问题,只需不要使用解构声明模式即可;直接访问状态或通过委托访问状态,如示例 1 和 2 所示。