Jetpack Compose 中的副作用

SideEffects in Jetpack Compose

我了解到,除了 compositioncomposable 中的行为,所有其他行为都是副作用。那么,在 TextField 的情况下,更改 onValueChange 中的 TextFieldValue 是否有副作用?另外,在 composable 中显示 toast 消息是否有副作用?

根据 Jetpack Compose 中 SideEffect 的定义,副作用是发生在可组合函数范围之外的应用程序状态更改。 在 TextField 中,我们无法通过交换值来更改文本字段的状态。 您可以在 CoreTextField Compose 函数中看到它:

            if (value != it) {
                onValueChange(it)
            }
        }, 

因此在 onValueChange 中,没有使用 SideEffects。

同样在 Toast 消息的情况下,但是 Toast 不是用 Compose 编写的,所以它不是一个 compose 函数,我们可以从 compose 函数外部调用它,所以没有副作用使用。

让我们先了解几个术语w.r.t函数式编程

Idempotent - 意味着调用相同的函数 n 次,提供相同的输入,应该产生相同的输出。

您的函数需要在 compose 世界中 idempotent,以便重组工作 - 作为 compose 运行time,memoizes 在初始合成期间,如果在 recomposition 期间输入函数没有改变(或者说树节点没有更新),compose 运行time 将使用相同的 memoized 结果。函数不是 idempotent 将导致重组期间出现意外行为。

Purefunction - 不包含副作用的函数。

Side-effect - 它是任何超出函数范围的操作,可以在侧面做一些意想不到的事情。

In compose world - side-effect could be a change to the state of the app that happens outside of the scope of the function, things like setting a global variable, updating cache, making a network query, reading from file etc.. 

It makes the function non-deterministic and can lead to race condition and unexpected behavior. 

To generalize, side-effects are unexpected actions happening on the side, out of what callers would expect from the function, and that alter its behavior.

正如我们所说,一个函数应该没有副作用,但是在少数情况下我们需要 运行 可组合的副作用,以处理这些情况 compose 运行-time 提供不同的effect-handlers,- 这将确保他们 运行 在正确的时间根据 compose 生命周期。

So, in the case of TextField, is changing the TextFieldValue in onValueChange a side effect?

对我来说它更像是一个 unidirectional 数据流,并且由于状态是在可组合项的范围内管理的(可组合项的内部存储器),所以它不是副作用。

Also, is it a side effect to display a toast message in composable?

这可能是一个副作用,如果处理不当,考虑到,你最终不会在重新组合时调用 toast。