Mr.Liu
文章3
标签4
分类3

文章归档

Compose的生命周期与重组(Recompose)

Compose的生命周期与重组(Recompose)

传统Android生命周期

在传统的Android开发中,Activity和Fragment是Android应用的两个主要组件,它们都有自己的生命周期。Activity和Fragment的生命周期方法如下:

还是老生常谈的生命周期,这里就不再赘述了。

Compose的生命周期

在Jetpack Compose中,组合(Composition)描述了应用的UI界面,并通过运行可组合项(Composable)生成描述界面树结构。

相比于Activity/Fragment的生命周期,Compose的生命周期更加简单

进入组合->0次或多次重组->离开组合

有时候我们需要在Composable的生命周期中做一些额外的操作,比如在进入组合时做一些初始化操作,或者在离开组合时做一些资源释放操作。Compose提供了一些副作用函数来帮助我们处理这些情况,比如DisposableEffectLaunchedEffectSideEffect等。

LaunchedEffect

LaunchedEffect是一个副作用函数,它在组合进入时执行,可以用来执行一些异步操作,比如网络请求、数据库查询等。

  • 使用常量,如Unit作为key时,表示只有在进入组合时执行一次,通常用来做一些初始化或获取数据的操作,不过通常要避免这种情况的使用
  • 使用其他参数作为key时,每次参数变化时都会取消之前的协程并重新启动一个新的协程,对于多个key,只要有一个key变化,就会重新启动一个新的协程(与React的useEffect类似,回调中使用的外部变量需要在key中传入)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Composable
fun MyComposable() {
    // 当LaunchedEffect进入组合时,启动一个协程
    LaunchedEffect(Unit) {
        
    }
    var data by remember { mutableStateOf("data") }
    // 当data变化时,取消之前的协程并重新启动一个新的协程
    LaunchedEffect(data) {
        Log.d("MyComposable", "data: $data")
    }
    Button(onClick = { data = "${data}1" }) {
        Text("Click me")
    }
}

rememberUpdatedState

一般在LaunchedEffect中,当其中一个键参数发生变化时,LaunchedEffect 会重启。 但在协程执行期间,外部状态可能会发生改变,如果不希望LaunchedEffect重启,需要使用rememberUpdatedState来获取最新的值,并移除传入的key,该值在发生改变时不会重启LaunchedEffect。

这种方法对于包含长期操作的效应十分有用,因为重启这些操作的代价可能会很高。

1
2
3
4
5
6
7
8
9
10
11
12
@Composable
fun LandingScreen(onTimeout: () -> Unit) {

    // 这将始终引用 LandingScreen 重构时最新的 onTimeout 函数
    val currentOnTimeout by rememberUpdatedState(onTimeout)

    // 创建与 LandingScreen 生命周期相匹配的效应。如果 LandingScreen 重新组合,则delay不应再次启动。
    LaunchedEffect(true) {
        delay(SplashWaitTimeMillis)
        currentOnTimeout()
    }
}

DisposableEffect

对于需要在key发生变化或可组合项退出组合后进行清理的附带效应,需要使用DisposableEffect

  • key发生变化时,DisposableEffect会调用onDispose中的回调函数,并重启DisposableEffect
  • 当可组合项退出组合时,DisposableEffect也会调用onDispose中的回调函数,用于清理资源。

下面是一个简单的例子,用于监听Composable的生命周期事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Composable
fun OnLifecycle(
    lifecycleEvent: Lifecycle.Event = Lifecycle.Event.ON_CREATE,
    onLifecycle: () -> Unit,
) {
    val lifecycleOwner = LocalLifecycleOwner.current
    val onLifecycle by rememberUpdatedState(newValue = onLifecycle::invoke)
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == lifecycleEvent) {
                onLifecycle()
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            // 在组件销毁时执行
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

这个例子中,我们定义了一个OnLifecycle组合,用于监听生命周期事件。如果lifecycleOwner改变,DisposableEffect会调用onDispose中的回调函数,并重启DisposableEffect

DisposableEffect中,我们添加了一个LifecycleEventObserver,用于监听生命周期事件。在onDispose中,我们移除了对应的LifecycleEventObserver,清理了监听事件,防止内存泄漏。

本文作者:Mr.Liu
本文链接:https://lzh666.top/2024/04/12/Compose%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%8E%E9%87%8D%E7%BB%84-Recompose/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可