美文网首页
LaunchedEffect 和 rememberUpdated

LaunchedEffect 和 rememberUpdated

作者: zcwfeng | 来源:发表于2023-05-25 11:41 被阅读0次

    Compose 中的附带效应是指发生在可组合函数作用域之外的应用状态的变化。例如,当用户点按一个按钮时打开一个新屏幕,或者在应用未连接到互联网时显示一条消息。

    Compose 中的附带效应是指发生在可组合函数作用域之外的应用状态的变化。将状态更改为显示/隐藏着陆屏幕的操作将发生在 onTimeout 回调中,由于在调用 onTimeout 之前我们需要先使用协程加载内容,因此状态变化必须发生在协程的上下文中!

    如需从可组合项内安全地调用挂起函数,请使用 LaunchedEffect API,该 API 会在 Compose 中触发协程作用域限定的附带效应。

    LaunchedEffect 进入组合时,它会启动一个协程,并将代码块作为参数传递。如果 LaunchedEffect 退出组合,协程将取消。

    虽然接下来的代码不正确,但让我们看看如何使用此 API,并探讨为什么下面的代码是错误的。我们将在此步骤的后面调用 LandingScreen 可组合项。

    // home/LandingScreen.kt file
    
    import androidx.compose.runtime.LaunchedEffect
    import kotlinx.coroutines.delay
    
    @Composable
    fun LandingScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
        Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            // Start a side effect to load things in the background
            // and call onTimeout() when finished.
            // Passing onTimeout as a parameter to LaunchedEffect
            // is wrong! Don't do this. We'll improve this code in a sec.
            LaunchedEffect(onTimeout) {
                delay(SplashWaitTime) // Simulates loading things
                onTimeout()
            }
            Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
        }
    }
    

    某些附带效应 API(如 LaunchedEffect)会将可变数量的键作为参数,用于在其中一个键发生更改时重新开始效应。您发现错误了吗?我们不希望在此可组合函数的调用方传递不同的 onTimeout lambda 值时重启 LaunchedEffect。这会让 delay 再次启动,使得我们无法满足相关要求。

    如果 onTimeout 在附带效应正在进行时发生变化,效应结束时不一定会调用最后一个 onTimeout。如需保证调用最后一个 onTimeout,请使用 rememberUpdatedState API 记住 onTimeout。此 API 会捕获并更新最新值:

    // home/LandingScreen.kt file
    
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.rememberUpdatedState
    import kotlinx.coroutines.delay
    
    @Composable
    fun LandingScreen(onTimeout: () -> Unit, modifier: Modifier = Modifier) {
        Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            // This will always refer to the latest onTimeout function that
            // LandingScreen was recomposed with
            val currentOnTimeout by rememberUpdatedState(onTimeout)
    
            // Create an effect that matches the lifecycle of LandingScreen.
            // If LandingScreen recomposes or onTimeout changes,
            // the delay shouldn't start again.
            LaunchedEffect(Unit) {
                delay(SplashWaitTime)
                currentOnTimeout()
            }
    
            Image(painterResource(id = R.drawable.ic_crane_drawer), contentDescription = null)
        }
    }
    

    当长期存在的 lambda 或对象表达式引用在组合期间计算的参数或值时,您应使用 rememberUpdatedState,这在使用 LaunchedEffect 时可能很常见。

    相关文章

      网友评论

          本文标题:LaunchedEffect 和 rememberUpdated

          本文链接:https://www.haomeiwen.com/subject/itbesdtx.html