为什么 snapshotFlow 使用 MutableState 作为属性委托进行触发?

Why snapshotFlow is trigged with MutableState as property delegate?

提问人:Thái Quốc Toàn 提问时间:10/24/2023 更新时间:10/24/2023 访问量:50

问:

我最近在尝试观察 MutableState 的变化时遇到了 snapshotFlow 的情况。这是代码片段

val searchQuery = mutableStateOf("")
snapshotFlow { searchQuery }.collectLatest {
               
}

但是当改变时,块中什么也没发生。似乎没有发现任何变化。我猜到了。然后我将 searchQuery 声明更改为 .snapshotFlow 按预期工作。谁能解释一下为什么?真的很感激!searchQuerycollectLatestsnapshotFlowsearchQueryvar searchQuery by mutableStateOf("")

安卓 android-jetpack-compose kotlin-flow mutable状态

评论

2赞 chuckj 10/24/2023
您需要读取 .例如snapshotFlowsearchQuery.value

答:

1赞 Thracian 10/24/2023 #1

snapshotFlow 从可观察的 Snapshot 状态创建 Flow。(例如 mutableStateOf 返回的状态容器。

如果 block 的结果不等于前一个结果,则流 将发出该新结果。(此行为类似于 Flow.distinctUntilChanged.)

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotFlow.kt;drc=e17d836265f395ae589ba254c4efddd29a314ae3;l=75

您正在查询 的实例,需要收集一个新的 。val searchQuery = mutableStateOf("")MutableStateMutableStateMutableState

下面的示例仅用于演示目的,除非明确要求,否则您不需要在 .我们正在收集查询。如果使用按钮分配新的 MutableState,则会看到 snapshotFlow 收集 MutableState 的新实例StateStatestate holderMutableState

@Preview
@Composable
private fun SnapshowFlowTest() {

    var query = remember {
        mutableStateOf(mutableStateOf(""))
    }

    LaunchedEffect(Unit) {
        snapshotFlow {
            query.value
        }
            .collect {
                println("State: $it, value: ${it.value}")
            }
    }

    Column {
        TextField(
            value = query.value.value,
            onValueChange = {
                query.value.value = it
            }
        )

        Button(
            onClick = {
                query.value = mutableStateOf("Default Value")
            }
        ) {
            Text("Set new MutableState")
        }
    }
}

您正在收集 MutableState 值的变化,即 String。var searchQuery by mutableStateOf("")

评论

0赞 ΓDΛ 10/24/2023
干净的答案。谢谢。我想知道的是,谷歌文档说我们可以通过 3 种不同的方式收听状态。他们为什么不说明它们之间的区别?developer.android.com/jetpack/compose/......
0赞 Thái Quốc Toàn 10/24/2023
有用的例子!我现在已经弄清楚了原因
1赞 BenjyTec 10/24/2023 #2

请参考这个 StackOverflow 答案

SnapshotFlow 的工作方式与重构类似 - 它跟踪 State.value 来知道何时发出。因此,要使 snapshotFlow 正常工作, 值必须在 snapshotFlow {} 块内读取,但该块不是 发生

使用您当前的方法,不知道要观察哪些变化。当使用关键字时,被隐式调用,因此可以检测到更改。snapshotFlowbysearchQuery.valuesnaphotFlow

要解决此问题,请尝试

val searchQuery = mutableStateOf("")
snapshotFlow { searchQuery.value }.collectLatest {
    // ...      
}

或使用关键字。by

由于官方文档对声明 MutableState 的方法有何不同仍然含糊不清,这篇 Reddit 帖子很好地总结了这些差异。

评论

0赞 ΓDΛ 10/24/2023
我想知道的是,谷歌文档说我们可以通过 3 种不同的方式收听状态。他们为什么不说明它们之间的区别?developer.android.com/jetpack/compose/......
1赞 BenjyTec 10/24/2023
@ΓDΛ 你在这里有一个有效的观点。这已经造成了混乱,并将造成进一步的混乱。我发现这个 Reddit 线程可以正确解释这三种方法之间的差异,这比您最初想象的要大:reddit.com/r/androiddev/comments/rqdv5g/......
0赞 Thái Quốc Toàn 10/24/2023
是的,我现在知道该走的路了