Jetpack Compose 重组竞争条件

Leo*_*tev 5 android race-condition kotlin android-jetpack-compose compose-recomposition

假设我们有以下代码。它显示一个按钮,当用户单击它时,该按钮就会消失。

@Composable
fun ButtonThatDisappearsOnClick() {
    var showButton by remember { mutableStateOf(true) }
    if (showButton) {
        Button(onClick = {
            check(showButton) { "onClick shouldn't be called for a hidden button" }  // !!!
            showButton = false
        }) {
            Text("My button")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我怀疑check如果用户快速单击按钮两次,上面的调用可能会失败:

  • 用户点击按钮,shouldShowButton设置为false。由于可变状态下的值已更新,因此安排了重组。
  • 在视图重新组合之前,用户再次快速单击该按钮。因此,该onClick函数将第二次触发,并且check调用将失败。

我无法在实践中重现这一点,所以我想知道这种行为是否确实可能。

Thr*_*ian 3

这个问题就是回答你所要求的。Op 连续更改值,但如果状态值在重组完成之前发生更改,则可能会丢弃先前的重组并安排新的重组。

如果连续设置两个值,MutableState 将忽略第一个值

SideEffect函数可用于仅在成功重组发生时才应调用的操作

每当 Compose 认为可组合项的参数可能已更改时,重组就会开始。重组是乐观的,这意味着 Compose 期望在参数再次更改之前完成重组。如果参数在重组完成之前发生更改,Compose 可能会取消重组并使用新参数重新启动。

当取消重组时,Compose 会从重组中丢弃 UI 树。如果您有任何依赖于所显示的 UI 的副作用,即使取消合成,也会应用副作用。这可能会导致应用程序状态不一致。

确保所有可组合函数和 lambda 都是幂等且无副作用的,以处理乐观重组。