Android Jetpack Compose基础之副作用Effect
什么是副作用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