LaunchedEffect:在Jetpack Compose中使用协程

在这里插入图片描述

LaunchedEffect


LaunchEffect允许我们在Composable中使用协程

@Composable fun DisposableEffect(
    vararg keys: Any?, 
    effect: DisposableEffectScope.() -> DisposableEffectResult
): Unit
  • DisposableEffect一样,当Composable进入composition时执行block
  • 当Composable从树上detach时,CoroutineScope执行cancel
  • 参数keys发生变化是,会执行cancel后再次执行effect

简而言之,就是支持执行Coroutine的DisposableEffect,会自动执行cancel,不需要手动onDispose


使用方法


使用方式如下:

@Composable
fun SplashScreen(
    onTimeOut: () -> Unit
) {
    
    
    LaunchedEffect(Unit) {
    
     
        delay(SplashWaitTime)
        onTimeOut()
    }
    ...
}

例如上面,在首次启动时显示开屏页。参数Unit,因为不会有diff,所以实现onActive的生命周期效果,即尽在首次composition时执行一次

@Composable
fun SearchScreen() {
    
    
    ...
    var searchQuery by remember {
    
     mutableStateOf("") }
    LaunchedEffect(searchQuery) {
    
    
        // execute search and receive result
    }
    ...
}

再如上,当检索词变化时,发起检索。

让Composable支持协程的重要意义是,可以让一些简单的业务逻辑直接Composable的形式封装并实现复用,而无需额外借助ViewModel。


实现原理


@Composable
@ComposableContract(restartable = false)
fun LaunchedEffect(
    subject: Any?,
    block: suspend CoroutineScope.() -> Unit
) {
    
    
    val applyContext = currentComposer.applyCoroutineContext
    remember(subject) {
    
     LaunchedEffectImpl(applyContext, block) }
}

实现非常简单,使用remember保存了subject参数,然后通过LaunchedEffectImpl启动协程

internal class LaunchedEffectImpl(
    parentCoroutineContext: CoroutineContext,
    private val task: suspend CoroutineScope.() -> Unit
) : CompositionLifecycleObserver {
    
    

    private val scope = CoroutineScope(parentCoroutineContext)
    private var job: Job? = null

    override fun onEnter() {
    
    
        job?.cancel("Old job was still running!")
        job = scope.launch(block = task)
    }

    override fun onLeave() {
    
    
        job?.cancel()
        job = null
    }
}

LaunchedEffectImpl可以提供CoroutineScope,借助CompositionLifecycleObserver提供的生命周期,进入屏幕时launch启动协程,离开屏幕时cancel取消协程。

猜你喜欢

转载自blog.csdn.net/vitaviva/article/details/114503797