首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JetPack合成中的副作用

JetPack合成中的副作用
EN

Stack Overflow用户
提问于 2022-02-28 07:34:59
回答 1查看 1.7K关注 0票数 2

虽然我理解或认为我理解,什么副作用是在喷气式包装组成。

代码语言:javascript
复制
It's any work done in composable which escapes the scope of the composable function

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

考虑到上面的一切,我需要在几个场景中有一点清晰。

  • 副作用-在变异对象的情况下,它是否适用于除组合对象以外的任何对象?如在组成状态(mutableStateOf等)不会产生副作用吗?为什么?
  • 为什么回调/状态/事件提升到活动/片段/视图模型,不会导致副作用?

,例如

代码语言:javascript
复制
@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还是回调?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-28 21:51:15

SideEffect并不意味着其他任何事情都不是副作用。它是一个转义舱口,应该考虑到事物的合成和效果,但不是或不能在节点树中表达。

例如,Dialog使用SideEffect来传递对话框属性、布局方向和从Dialog参数中剔除回调到作为组合结果创建的Android对话框。这就产生了一种错觉,即尽管Dialog使用视图系统来创建对话框,但它本身就是Compose的一部分。

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

副作用-在变异对象的情况下,它是否适用于除组合对象以外的任何对象?如在组成状态(mutableStateOf等)不会产生副作用吗?为什么?

可组合函数只应读取这些对象中的状态;它不应修改此状态。对于可观察的状态(如mutableStateOf ),编写对此状态的观察更改,并对读取状态的可组合函数进行重新组合。您可以使用mutableStateOf来执行副作用;不应该这样做。

为什么回调/状态/事件提升到您的活动/片段/视图模型,不会导致副作用?

如果正确使用,就不会;从撰写的角度看也不会。组合函数是从它们读取的数据到用户界面树的转换函数。当视图模型发生变化时,将对转换进行增量重新评估,以生成视图模型的新状态所隐含的UI。状态提升允许应用程序中具有更多上下文的更高级别的部分来控制应用程序中较低级别、更通用的部分的状态,这些部分对数据应该如何存储和/或验证具有更多的上下文。已挂起状态的组件不应写入状态。如果它们需要声明要更改,则应该使用新的所需状态调用事件处理程序,或者描述要进行的更改(例如,DeleteCustomer #1234)。应该由提供的事件处理程序实际对悬挂状态进行更改。

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

不,它不是。它初始化state,因为状态不转义,组合被认为是组合的一部分。这不是推荐的做法,但不是副作用。

launchSomeActivity()

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

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

这是一个副作用,因为同样的原因,同样的答案。

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

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71291835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档