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() // 取消协程
    

    Kotlin协程(二)协程的生命周期及管理_第1张图片 

    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 销毁时取消协程

     

    你可能感兴趣的:(协程,kotlin,开发语言,android)