在 Kotlin 中,协程的生命周期 主要涉及 创建(Starting)、执行(Active)、挂起(Suspended)、取消(Cancelled) 和 完成(Completed) 这些状态。协程的生命周期受 CoroutineScope 和 Job 控制。
Kotlin 协程的生命周期可以分为以下几个阶段:
launch
或 async
创建协程,但协程还未执行。val job = GlobalScope.launch {
// 协程代码
}
协程开始执行,进入 Active 状态。
这包括:
launch
立即执行)delay
结束后恢复)val job = GlobalScope.launch {
println("协程开始执行") // Active
}
协程执行 delay()
、suspend fun
等操作,暂停执行,不会阻塞线程。
之后可以恢复执行。
val job = GlobalScope.launch {
println("协程启动")
delay(2000) // 挂起
println("协程恢复")
}
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() // 取消协程
协程正常执行完毕,变为 Completed 状态。
val job = GlobalScope.launch {
println("任务完成")
}
job.invokeOnCompletion {
println("协程结束")
}
等待子协程
+-----+ start +--------+ complete +-------------+ finish +-----------+
| 新建 | -----> | Active | --------> | Completing | -------> | 已完成 |
+-----+ +--------+ +-------------+ +-----------+
| 取消 / 失败 |
| +----------------+
| |
V V
+------------+ 完成 +-----------+
| 取消中 | --------------------------------> | 已取消 |
+------------+ +-----------+
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
invokeOnCompletion
监听完成状态val job = GlobalScope.launch {
delay(1000)
println("任务完成")
}
job.invokeOnCompletion { cause ->
if (cause == null) {
println("协程成功完成")
} else {
println("协程被取消,原因:$cause")
}
}
job.cancel()
CoroutineScope
影响生命周期CoroutineScope |
说明 | 生命周期 |
---|---|---|
GlobalScope |
应用级作用域,协程与进程同生命周期 | 进程结束时才取消 |
CoroutineScope |
自定义作用域,需要手动取消 | 作用域内有效 |
viewModelScope |
适用于 ViewModel ,随 ViewModel 销毁而取消 |
ViewModel 结束时取消 |
lifecycleScope |
适用于 Activity /Fragment ,随生命周期变化 |
Activity/Fragment 结束时取消 |
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()
,可能会继续运行一段时间。New
→ Active
→ Suspended
→ Cancelled
→ Completed
Job
控制 isActive
、cancel()
以及 invokeOnCompletion()
viewModelScope
适用于 ViewModel