gpt4 book ai didi

android - JetPack Compose 中的副作用

转载 作者:行者123 更新时间:2023-12-02 01:43:10 27 4
gpt4 key购买 nike

虽然我了解或自认为了解,但 Jet-pack Compose 中有哪些副作用。

It's any work done in composable which escapes the scope of the composable function

我理解做一些事情,比如 I/O 操作或在函数范围之外改变一个变量,提供引用而不清除它(内存泄漏),或者改变一个不可组合状态的局部变量——这些都是副作用,因为它们可能会由于重组而导致意外行为和泄漏,重组是不确定的并且可以运行多次。为了处理副作用,我们有效果处理程序。

考虑到以上所有内容,我需要在一些情况下弄清楚

  • 副作用——在改变对象的情况下,它是否适用于除组合对象以外的任何对象?在组合状态(mutableStateOf 等)中不会导致副作用吗?为什么?
  • 为什么将回调/状态/事件提升到您的 Activity/fragment/ View 模型不会导致副作用?

例如

@Composable
fun MyComposable(
viewModel:MyViewModel,
launchSomeActivity:()->Unit
){
var state by remember { mutableStateOf("") }
state = "some string" // not a side-effect?

viewModel.someStringObject = "a" // it's a side-effect?

launchSomeActivity() // it's a side-effect?

when(val screenState = viewModel.screenState.collectAsState().value){
is ScreenState.Success -> launchSomeActivity() // not a side-effect. why?
is ScreenState.Error -> state="some String" // not a side-effect. why?
}
}

我还记得在某处读过,触发回调的副作用,例如 onClick 因为它总是在 UI 线程上执行,或者说从 ViewModel 调用一些 lambda。

是否也想了解上述场景,以及它如何防止副作用、调用 lambda 或回调?

最佳答案

SideEffect 并不意味着其他任何东西都不是副作用。它是应该考虑的事情和组合的影响但没有或不能在节点树中表达的逃生舱口。

例如,Dialog 使用 SideEffectDialog 参数中的对话框属性、布局方向和关闭回调传递给 Android 对话框作为组合的结果创建。这给人一种错觉,即 Dialog 本身就是 Compose 的一部分,即使它使用 View 系统创建对话框也是如此。

一般来说,组合函数应该只读取状态,而不是修改状态。如果它确实修改了状态,那么它应该只修改在组合期间创建的状态,并由创建状态的可组合函数直接调用的可组合函数使用;并且仅在任何 child 阅读状态之前,而不是之后。

Side-effect - in case of mutating object, does it holds true for any object other than compose object? As in compose states (mutableStateOf etc..) doesn't lead to side-effects? Why?

可组合函数应该只读取这些对象中的状态;它不应该修改这个状态。对于可观察状态,例如 mutableStateOf,Compose 会观察此状态的变化,并将安排读取状态的可组合函数的重组。您可以使用 mutableStateOf 来执行副作用;你不应该。

Why callbacks/state/event hoisting to your activity/fragment/viewmodel,does not lead to side-effect?

如果使用得当,不会,不会;不是从 Compose 的角度来看。组合函数是从它们读取的数据到用户界面树的转换函数。随着 View 模型的更改,将逐步重新评估转换以生成 View 模型的新状态所暗示的 UI。状态提升允许应用程序的较高级别部分在数据应如何存储和/或验证方面具有更多上下文,以控制应用程序较低级别、更通用部分的状态。已提升状态的组件不应该写入状态。如果他们需要更改状态,则应使用新的所需状态或对要进行的更改的描述调用事件处理程序(例如 DeleteCustomer #1234)。实际更改提升状态应该由提供的事件处理程序决定。

state = "some string" // not a side-effect?

不,不是。它初始化 state,因为 state 没有逃脱组合被认为是组合的一部分。这不是推荐的做法,但它不是副作用。

launchSomeActivity()

这是一个副作用,应该在 LaunchEffect 中执行,它将在一个范围内启动协程,当组合中不再调用组合函数时,该范围将自动取消。

is ScreenState.Success -> launchSomeActivity() // not a side-effect. why?

这是出于相同原因和相同答案的副作用。

is ScreenState.Error -> state="some String" // not a side-effect. why?

这不是上面提到的副作用(即副作用意味着它对组合之外的东西有影响,但事实并非如此),但是,如果 state 已经read then 它被认为是向后写并且非常不鼓励,因为它可能导致重复组合,也许无限期地重复;因为任何已经读取过的内容都可能会重新安排再次执行。

关于android - JetPack Compose 中的副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71291835/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com