在 jetpack compose 中使用 LaunchedEffect 与 SideEffect

Viv*_*odi 8 android kotlin android-jetpack android-jetpack-compose

大家好,我正在学习项目中的副作用。我想知道什么时候应该使用LaunchedEffect以及SideEffect在什么情况下使用。我正在添加一些使用这两种效果的代码。如果我在这里做错了,请让我知道。

第一次使用 LaunchedEffect,请指导我是否需要此功能的效果。

@Composable
fun BluetoothRequestContinue(multiplePermissionsState: MultiplePermissionsState) {
    var launchPermission by remember { mutableStateOf(false) }
    if (launchPermission) {
        LaunchedEffect(Unit) {
            multiplePermissionsState.launchMultiplePermissionRequest()
        }
    }
    AbcMaterialButton(
        text = stringResource(R.string.continue_text),
        spacerHeight = 10.dp
    ) {
        launchPermission = true
    }
}
Run Code Online (Sandbox Code Playgroud)

第二次使用 SideEffect 使用意图打开设置

@Composable
fun OpenPermissionSetting(router: Router = get()) {
    val activity = LocalContext.current as Activity
    var launchSetting by remember { mutableStateOf(false) }
    if (launchSetting) {
        SideEffect {
            activity.startActivity(router.permission.getPermissionSettingsIntent(activity))
        }
    }
    AbcMaterialButton(
        text = stringResource(R.string.open_settings),
        spacerHeight = 10.dp
    ) {
        launchSetting = true

    }
}
Run Code Online (Sandbox Code Playgroud)

请告诉我我们是否需要效果。如果我们也需要不同的效果,请指导我。谢谢

Thr*_*ian 18

之间有区别

   if (launchSetting) {
        SideEffect {
            // Do something
        }
    }
Run Code Online (Sandbox Code Playgroud)

   if (launchPermission) {
        LaunchedEffect(Unit) {
            multiplePermissionsState.launchMultiplePermissionRequest()
        }
    }
Run Code Online (Sandbox Code Playgroud)

当条件为真时,两者都会进入重组,但LaunchedEffect只调用一次,因为它的键是UnitSideEffect只要条件为真,就会在每次重组时调用。

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

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

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

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

官方文档中的示例

要与不受 compose 管理的对象共享 Compose 状态,请使用 SideEffect 可组合项,因为它会在每次成功的重组时调用。

@Composable
fun rememberAnalytics(user: User): FirebaseAnalytics {
    val analytics: FirebaseAnalytics = remember {
        /* ... */
    }

    // On every successful composition, update FirebaseAnalytics with
    // the userType from the current User, ensuring that future analytics
    // events have this metadata attached
    SideEffect {
        analytics.setUserProperty("userType", user.userType)
    }
    return analytics
}
Run Code Online (Sandbox Code Playgroud)

LaunchedEffect用于在键更改时调用组合或重新组合的函数。

如果你将 LaunchedEffect 写为

LaunchedEffect(key1= launchPermission) {
   if(launchPermission) {
     // Do something
  }
}
Run Code Online (Sandbox Code Playgroud)

如果 key 不为 true,则 if 内的代码块不会被组合调用,但每当它从 false 变为 true 时,代码块就会被调用。这对于不是由用户交互直接触发的一次性操作很有用,或者当操作需要在用户交互、动画或调用挂起函数(例如,lazyListState.animateScrollToItem()

维基百科中副作用概念的定义

在计算机科学中,如果一个操作、函数或表达式修改了其本地环境之外的某些状态变量值,则该操作、函数或表达式被认为具有副作用,也就是说,除了返回一个值的主要效果之外,它是否还有任何可观察到的效果操作调用者的值。示例副作用包括修改非局部变量、修改静态局部变量、修改通过引用传递的可变参数、执行 I/O 或调用具有副作用的其他函数。在存在副作用的情况下,程序的行为可能取决于历史;也就是说,评估的顺序很重要。理解和调试具有副作用的函数需要了解上下文及其可能的历史。