前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jetpack Compose - Effect与协程

Jetpack Compose - Effect与协程

作者头像
码客说
发布2024-03-29 12:54:07
2180
发布2024-03-29 12:54:07
举报
文章被收录于专栏:码客

Effect(生命周期)

在 Jetpack Compose 中,没有像传统 Android 中的生命周期函数那样的概念。

相反,Compose 依赖于函数式编程范式,它通过函数调用和状态变化来管理 UI 的渲染和更新。

Compose 中最重要的概念是 Composable 函数,这些函数负责描述 UI 的外观和行为,它们在需要时被调用来重新构建 UI。

尽管没有像传统 Android 中那样的生命周期函数,但您可以通过使用 Jetpack Compose 中提供的一些特定函数来模拟一些生命周期事件。

这些函数包括:

DisposableEffect

当 composable 进入树时,执行一个效果,并在 composable 从树中移除时清理资源。类似于 onDestroy()

代码语言:javascript
复制
DisposableEffect(Unit) {
    // 初始化操作,类似于 onCreate()
    
    onDispose {
        // 清理资源,类似于 onDestroy()
    }
}

SideEffect

在 composable 的每次重新组合时都会运行的效果。可以在此处执行类似于 onResume() 的操作。

SideEffect 只会在重组结束之后 被执行

代码语言:javascript
复制
SideEffect {
    // 每次重新组合时都会运行,类似于 onResume()
}

LaunchedEffect

这个和上面2个作用就不太一样了

用于启动一个协程来执行特定的操作,是在Compose组件被第一次创建时开始,并在Compose组件的生命周期中自动取消该协程。

LaunchedEffect的执行是异步的。

这个Effect主要的作用主要是在Compose中启动一个协程 而且具有2个特点

  1. 在重组过程完成以后 才会启动协程
  2. key 发生变化的时候 也会启动协程
代码语言:javascript
复制
LaunchedEffect(Unit) {
}

这些函数可以用于执行各种操作,以模拟传统 Android 生命周期中的行为。

但是请注意,Compose 的方式更加灵活和函数式,因此可能需要调整您的思维方式来适应这种新的 UI 构建模式。

代码语言:javascript
复制
@Composable
fun CounterView() {
    var count by remember { mutableStateOf(0) }
    DisposableEffect(Unit) {
        // 初始化操作,类似于 onCreate()
        Log.i("Effect","DisposableEffect-Create")
        onDispose {
            // 清理资源,类似于 onDestroy()
            Log.i("Effect","SideEffect-Dispose")
        }
    }
    LaunchedEffect(Unit) {
        // 初始化操作,类似于 onCreate()
        Log.i("Effect","LaunchedEffect")
    }
    SideEffect {
        Log.i("Effect","SideEffect")
    }
    Column(
        modifier = Modifier.padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("数量: $count")
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = { count++ }) {
            Text("计数器")
        }
    }
}

组件加载实际掉用的顺序

DisposableEffect-Create => SideEffect => LaunchedEffect

Kotlin 协程

Kotlin 协程是 Kotlin 标准库中的一个功能强大且流行的特性,用于简化异步编程。它允许开发者以顺序化的方式编写异步代码,而无需手动管理线程。

在 Android 开发中,Kotlin 协程与 Jetpack Compose 结合使用可以更轻松地处理异步操作,并且使 UI 代码更加清晰和易于维护。

  1. 协程作用域 (Coroutine Scope):用于定义协程的生命周期和作用范围。
  2. 协程构建器 (Coroutine Builders):例如 launchasyncrunBlocking 等,用于启动新的协程或创建异步任务。
  3. 挂起函数 (Suspending Functions):可以被暂停并在后续恢复执行的函数,使用 suspend 关键字声明。
  4. 调度器 (Dispatcher):用于指定协程执行的线程或线程池,包括 Dispatchers.DefaultDispatchers.IODispatchers.Main 等。
  5. 协程上下文 (Coroutine Context):包含协程的各种配置信息,例如调度器、异常处理器等。
  6. 协程作用域中的取消 (Cancellation):通过取消协程作用域来取消所有相关的协程,防止内存泄漏和资源浪费。

Jetpack Compose中使用协程

在 Jetpack Compose 中,您可以使用 Kotlin 协程来处理异步任务,例如从网络请求数据、执行数据库操作等。

定义协程作用域

在 Composable 函数中创建一个协程作用域,以确保协程在正确的生命周期范围内执行。

代码语言:javascript
复制
@Composable
fun MyComposable() {
    val coroutineScope = rememberCoroutineScope()

    // 在协程作用域中启动异步任务
    coroutineScope.launch {
        // 执行异步操作,例如网络请求或数据库查询
    }
}

创建协程作用域有两种方式

代码语言:javascript
复制
val coroutineScope = rememberCoroutineScope()

或者

代码语言:javascript
复制
val coroutineScope = CoroutineScope(Dispatchers.Main)

使用协程构建器

在协程作用域中使用协程构建器(例如 launchasync)启动异步任务。

代码语言:javascript
复制
val coroutineScope = rememberCoroutineScope()

coroutineScope.launch {
    // 在后台线程执行耗时操作
    val result = withContext(Dispatchers.IO) {
        // 执行耗时操作,例如网络请求或数据库查询
        // 等待3秒钟
        Log.i("Thread", "请求数据 Current thread: ${Thread.currentThread().name}")
        delay(3000L)
        "我是返回的数据"
    }

    // 在主线程更新 UI
    Log.i("Thread", "Data: ${result} Current thread: ${Thread.currentThread().name}")
}

处理协程中的异常

使用 try-catch 块或 CoroutineExceptionHandler 来处理协程中可能出现的异常。

代码语言:javascript
复制
coroutineScope.launch {
    try {
        // 执行可能抛出异常的代码
    } catch (e: Exception) {
        // 处理异常
    }
}

取消协程

在 Composable 组件的生命周期结束时,取消相关的协程以释放资源并避免内存泄漏。

代码语言:javascript
复制
@Composable
fun MyComposable() {
    val coroutineScope = rememberCoroutineScope()

    DisposableEffect(Unit) {
        onDispose {
            // 取消协程作用域中的所有协程
            coroutineScope.cancel()
        }
    }

    // 在协程作用域中启动异步任务
    coroutineScope.launch {
        // 执行异步操作
    }
}

通过以上步骤,您可以在 Jetpack Compose 中有效地利用 Kotlin 协程来管理异步任务,提高代码的可读性和可维护性。

同时,确保适当处理取消操作和异常,以确保应用程序的稳定性和性能。

协程作用域

CoroutineScope(Dispatchers.Main)rememberCoroutineScope()的区别:

CoroutineScope(Dispatchers.Main)rememberCoroutineScope() 都是用于创建协程作用域的方法,

但在使用上有一些区别:

CoroutineScope(Dispatchers.Main)

  • 这是一个函数调用,用于创建一个新的协程作用域,并指定其所在的调度器为主线程(Dispatchers.Main)。
  • 每次调用 CoroutineScope(Dispatchers.Main) 都会创建一个新的协程作用域对象,这意味着它可能在每次调用时创建新的作用域,而不考虑之前是否已存在作用域。
  • 如果在 Composable 函数中的多个地方需要使用相同的协程作用域,可能会导致创建多个不必要的作用域对象,从而增加了资源消耗和管理复杂度。

rememberCoroutineScope()

  • 这是一个 Composable 函数,用于在 Composable 中创建一个记住的(remembered)协程作用域。
  • rememberCoroutineScope() 会创建一个协程作用域对象,并将其与当前 Composable 的生命周期相关联。 这意味着,当 Composable 重新组合(recompose)时,它会保留相同的协程作用域对象,而不是每次重新组合都创建一个新的。
  • 因此,使用 rememberCoroutineScope() 可以确保在同一个 Composable 函数中共享相同的协程作用域,而不会导致额外的对象创建和资源浪费。

总的来说,CoroutineScope(Dispatchers.Main) 适用于那些不需要记住作用域对象的简单情况,而 rememberCoroutineScope() 则更适合于需要在 Composable 中共享和记住作用域对象的情况。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Effect(生命周期)
  • Kotlin 协程
  • Jetpack Compose中使用协程
  • 协程作用域
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档