Android Jetpack Compose基础之Side-Effect副作用

本文介绍了AndroidJetpackCompose中的副作用管理机制,包括DisposableEffect用于感知生命周期变化、LaunchedEffect执行异步任务、rememberCoroutineScope和rememberUpdatedState控制状态更新,以及如何通过derivedStateOf优化计算性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是副作用Side Effect

官方解释:发生在可组合函数作用域之外的应用状态的变化叫做副作用
由于可组合项的生命周期和属性(例如不可预测的重组、以不同顺序执行可组合项的重组或可以舍弃的重组),可组合项在理想情况下应该是无副作用的。

Composable在执行过程中,凡事会影响外界的操作都属于副作用,比很多一次性的事件如Toast、保存文件、获取远程或本地数据。因重组会造成Composabl频繁执行,显然这些事件不应该反复被执行,所以我们需要使用Compose提供的副作用API;
它作用是让副作用API只发生在Composable生命周期的特定阶段,从而实现行为可预期。【实现监控Compsable的生命周期变化】

DisposableEffect

源码

@Composable
@NonRestartableComposable
fun DisposableEffect(
    key1: Any?,
    effect: DisposableEffectScope.() -> DisposableEffectResult
) {
   
   
    remember(key1) {
   
    DisposableEffectImpl(effect) }
}

interface DisposableEffectResult {
   
   
    fun dispose()
}

private val InternalDisposableEffectScope = DisposableEffectScope()

private class DisposableEffectImpl(
    private val effect: DisposableEffectScope.() -> DisposableEffectResult
) : RememberObserver {
   
   
    private var onDispose: DisposableEffectResult? = null
    //Called when this object is successfully remembered by a composition. 
    //This method is called on the composition's apply thread.
    override fun onRemembered() {
   
   
        onDispose = InternalDisposableEffectScope.effect()
    }
	//Called when this object is forgotten by a composition. 
	//This method is called on the composition's apply thread.
    override fun onForgotten() {
   
   
        onDispose?.dispose()
        onDispose = null
    }
	//Called when this object is returned by the callback to remember 
	//but is not successfully remembered by a composition.
    override fun onAbandoned() {
   
   
        // Nothing to do as [onRemembered] was not called.
    }
}
/**
 * Receiver scope for [DisposableEffect] that offers the [onDispose] clause that should be
 * the last statement in any call to [DisposableEffect].
 */
class DisposableEffectScope {
   
   
    /**
     * Provide [onDisposeEffect] to the [DisposableEffect] to run when it leaves the composition
     * or its key changes.
     */
     //【方法3】:这个方法必须实现啦啦啦啦
    inline fun onDispose(
        crossinline onDisposeEffect: () -> Unit
    ): DisposableEffectResult = object : DisposableEffectResult {
   
   
        override fun dispose() {
   
   
            onDisposeEffect()
        }
    }
}

作用

他可以感知Composable生命周期中的加入组合和退出组合的变化,加入组合它会启动一个协程,并将代码块作为参数传递,当键发生变化或退出组合协程将自动取消并回调OnDispose(标注方法3),从而实现注销回调,避免泄漏。

示例


/**
 * DisposableEffect 对于需要在键发生变化或可组合项退出组合后进行清理的附带效应
 */
@Composable
fun onObserverLifecycleScreen(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, onStart: () -> Unit, onStop: () -> Unit
) {
   
   
    //为了确保 onStart lambda 始终包含重组 onObserverLifecycleScreen 时使用的最新值
    val currentOnStart by rememberUpdatedState(newValue = onStart)
    //可监听组合项退出组合时的回调,及控件销毁使的挂起销毁的回调操作
    val currentOnStop by rememberUpdatedState(newValue = onStop) 
    DisposableEffect(key1 = lifecycleOwner) {
   
   
        val observer = LifecycleEventObserver {
   
    source, event ->
            if (event == Lifecycle.Event.ON_START) {
   
   
                currentOnStart()
            } else if (event == Lifecycle.Event.ON_STOP) {
   
   
                currentOnStop()
            }
        }
        Log.i("SideEffect","onObserverLifecycleScreen DisposableEffect addObserver $observer")
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
   
   
            Log.i("SideEffect","onObserverLifecycleScreen DisposableEffect onDispose")
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

SideEffect

源码

@Composable
@NonRestartableComposable
@ExplicitGroupsComposable
@OptIn(InternalComposeApi::class)
fun SideEffect(
    effect: () -> Unit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值