当前位置: 首页 > news >正文

Kotlin协程(二)协程的生命周期及管理

在 Kotlin 中,协程的生命周期 主要涉及 创建(Starting)执行(Active)挂起(Suspended)取消(Cancelled)完成(Completed) 这些状态。协程的生命周期受 CoroutineScopeJob 控制。

1. 协程的生命周期状态

Kotlin 协程的生命周期可以分为以下几个阶段:

🔹 1.1 新建(New)

  • 调用 launchasync 创建协程,但协程还未执行。
  • 示例
val job = GlobalScope.launch {
    // 协程代码
}

    🔹 1.2 运行(Active)

    • 协程开始执行,进入 Active 状态。

    • 这包括:

      • 立即执行的协程(默认情况下,launch 立即执行)
      • 被恢复的协程(例如 delay 结束后恢复)
    val job = GlobalScope.launch {
        println("协程开始执行") // Active
    }
    

    🔹 1.3 挂起(Suspended)

    • 协程执行 delay()suspend fun 等操作,暂停执行,不会阻塞线程。

    • 之后可以恢复执行。

    val job = GlobalScope.launch {
        println("协程启动")
        delay(2000) // 挂起
        println("协程恢复")
    }
    

    🔹 1.4 取消(Cancelling)

    • job.cancel() 取消协程,进入 Cancelling 状态,随后变成 Cancelled

    • 需要 检查 isActive 或使用 ensureActive() 避免取消后继续执行。

    val job = GlobalScope.launch {
        repeat(100) { i ->
            if (!isActive) return@launch  // 取消检查
            println("运行中:$i")
            delay(500)
        }
    }
    delay(2000)
    job.cancel() // 取消协程
    

     

    🔹 1.5 完成(Completed)

    • 协程正常执行完毕,变为 Completed 状态。

    val job = GlobalScope.launch {
        println("任务完成")
    }
    job.invokeOnCompletion {
        println("协程结束")
    }
    
                                    等待子协程
     +-----+ start  +--------+ complete      +-------------+  finish    +-----------+
     | 新建 | -----> | Active  | --------> | Completing      | -------> | 已完成     |
     +-----+        +--------+           +-------------+          +-----------+
                       |  取消 / 失败      |
                       |   +----------------+
                       |   |
                       V   V
                 +------------+                          完成  +-----------+
                 | 取消中    | --------------------------------> | 已取消     |
                 +------------+                                   +-----------+

     

    2. 协程生命周期管理

    2.1 通过 Job 监听状态

    val job = GlobalScope.launch {
        delay(1000)
        println("任务完成")
    }
    
    println(job.isActive)   // true(运行中)
    println(job.isCompleted) // false
    println(job.isCancelled) // false
    
    job.cancel()
    println(job.isCancelled) // true
    

    2.2 通过 invokeOnCompletion 监听完成状态

    val job = GlobalScope.launch {
        delay(1000)
        println("任务完成")
    }
    
    job.invokeOnCompletion { cause ->
        if (cause == null) {
            println("协程成功完成")
        } else {
            println("协程被取消,原因:$cause")
        }
    }
    
    job.cancel()
    

    3. 不同 CoroutineScope 影响生命周期

    CoroutineScope说明生命周期
    GlobalScope应用级作用域,协程与进程同生命周期进程结束时才取消
    CoroutineScope自定义作用域,需要手动取消作用域内有效
    viewModelScope适用于 ViewModel,随 ViewModel 销毁而取消ViewModel 结束时取消
    lifecycleScope适用于 Activity/Fragment,随生命周期变化Activity/Fragment 结束时取消

     4. Job.cancel() vs Job.cancelAndJoin()

    • job.cancel() 立即取消,不会等待子协程完成。

    • job.cancelAndJoin() 取消后等待协程完全结束

    val job = GlobalScope.launch {
        repeat(100) { i ->
            println("运行中:$i")
            delay(500)
        }
    }
    
    delay(2000)
    job.cancelAndJoin() // 确保协程完全结束
    println("协程已取消")
    

    cancelAndJoin():这里 "协程已取消" 一定在协程结束后才会打印,不会有 "运行中:4" 出现。 

    🔹使用cancel()  "协程已取消" 可能在日志中提前出现?

    运行中:0
    运行中:1
    运行中:2
    运行中:3
    协程已取消
    运行中:4   // 可能仍然出现
    运行中:5   // 可能仍然出现
    ...
    
    • cancel() 只是请求取消,但 println("协程已取消") 不等待协程真的结束,主线程会立即继续执行。
    • 如果协程未及时检查 isActive 或执行 delay(),可能会继续运行一段时间

    总结

    1. 协程的生命周期状态NewActiveSuspendedCancelledCompleted
    2. 管理协程状态:使用 Job 控制 isActivecancel() 以及 invokeOnCompletion()
    3. 选择合适的 CoroutineScope:如 viewModelScope 适用于 ViewModel
    4. 避免内存泄漏:在 Activity/Fragment 销毁时取消协程

     

    相关文章:

  • 在Vscode开发QT,完成QT环境的配置
  • 体育数据分析:竞技表现优化与商业价值挖掘的技术范式
  • Golang的数据库分库分表
  • AI 外呼产品架构解读:让智能外呼更精准高效
  • PDF万能水印删除工具
  • 利用Adobe Acrobat 实现PPT中图片分辨率的提升
  • 自己编译RustDesk,并将自建ID服务器和key信息写入客户端
  • java 项目中设计模式 之单例模式
  • 简述一下Spark中的hashShuffle和Sortshuffle两中shauffle的流程
  • 命名管道——进程间通信
  • 【JAVA面试题】设计模式之原型模式
  • 安装Linux操作系统
  • uni-app开发安卓和iOS 打包流程(云打包)
  • 代码随想录刷题学习日记
  • Oracle 11g的部署配置
  • go语言中字符串嵌套
  • 表格管理---React
  • Ubuntu 20.04下配置VSCode以支持ROS开发
  • Mysql面试篇笔记:
  • k8s架构及服务详解
  • 巴基斯坦外长:印巴停火
  • 泰特现代美术馆25年:那些瞬间,让艺术面向所有人
  • 五粮液董事长:茅台1935已脱离千元价位带,五粮液在千元价位已逐步摆脱其他竞品纠缠
  • 代理销售保险存在误导行为,农业银行重庆市分行相关负责人被罚款0.1万元
  • 洞天寻隐·学林纪丨玉洞桃源:仇英青绿山水画中的洞天与身体
  • 商务部再回应中美经贸高层会谈:美方要拿出诚意、拿出行动