1. CoroutineScope
是什么?
CoroutineScope
定义了协程的生命周期,它用于管理协程的启动、取消,并确保协程在 Scope
结束时自动取消,避免内存泄漏。
2. CoroutineScope
的使用方式
(1) 直接创建 CoroutineScope
val scope = CoroutineScope(Dispatchers.IO) // 绑定 IO 线程
fun startTask() {
scope.launch {
println("运行在 ${Thread.currentThread().name}") // IO 线程
delay(2000)
println("任务完成")
}
}
🔹 优点:可以手动控制 scope.cancel()
来管理协程生命周期。
🔹 缺点:如果不手动取消,scope
可能导致内存泄漏。
(2) GlobalScope
(全局作用域,不推荐)
fun test() {
GlobalScope.launch {
delay(1000)
println("全局协程完成")
}
}
🔹 特性
- 全局作用域,不会自动取消(除非应用进程终止)。
- 适用于 App 全局任务(如日志、统计)。
- ⚠️ 但不推荐用于普通任务,因为它可能导致内存泄漏!
(3) coroutineScope
(挂起当前协程,推荐)
suspend fun test() {
coroutineScope {
launch {
delay(1000)
println("子协程完成")
}
println("coroutineScope 结束") // 先输出
}
}
🔹 特性
- 不会阻塞线程,但会等待子协程完成再返回。
- 适用于
suspend fun
,不适用于main
函数。
3. CoroutineScope
的特性
特性 | CoroutineScope() | GlobalScope | runBlocking | coroutineScope |
---|---|---|---|---|
作用域大小 | 受 scope 限制 | 全局 | 当前线程 | 当前协程 |
线程阻塞 | ❌ 否 | ❌ 否 | ✅ 是 | ❌ 否 |
自动取消 | ✅ 是 | ❌ 否 | ✅ 是 | ✅ 是 |
适用场景 | 组件生命周期管理 | 全局任务(慎用) | 测试 | suspend 函数 |
4. CoroutineScope
的生命周期管理
(1) 在 ViewModel
中使用
viewModelScope
自动绑定ViewModel
生命周期,在ViewModel
销毁时会自动取消协程。
class MyViewModel : ViewModel() {
private val viewModelScope = ViewModelScope() // Android 提供的作用域
fun fetchData() {
viewModelScope.launch {
val data = withContext(Dispatchers.IO) { fetchFromNetwork() }
println("数据获取完成: $data")
}
}
}
(2) 在 Activity
或 Fragment
中使用
onDestroy()
时,job.cancel()
自动取消所有协程,避免泄漏。
class MyActivity : AppCompatActivity(), CoroutineScope {
private val job = Job()
override val coroutineContext = Dispatchers.Main + job // 绑定主线程
override fun onDestroy() {
super.onDestroy()
job.cancel() // 取消所有协程
}
fun startTask() {
launch {
delay(1000)
println("任务完成")
}
}
}
如果担心自己忘了取消job,推荐使用lifecycleScope
lifecycleScope
是 AndroidX Lifecycle 提供的 Lifecycle-aware(生命周期感知)协程作用域。它的 特点:
- 自动取消协程,在
Activity
或Fragment
销毁 时,lifecycleScope
会 自动取消所有未完成的协程,避免内存泄漏。 - 跟随生命周期,
lifecycleScope
的生命周期绑定到LifecycleOwner
(如 Activity、Fragment),任务会在onDestroy()
时自动取消。 - 简洁,直接使用,不需要手动管理
Job
,代码更清晰。
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun startTask() {
lifecycleScope.launch {
delay(1000)
println("任务完成")
}
}
}
5. CoroutineScope
与 Job
的关系
-
CoroutineScope
需要Job
来管理生命周期。 -
CoroutineScope(Dispatchers.Main + Job())
:可以手动取消所有协程。 -
scope.cancel()
取消所有子协程,防止任务泄漏。
val scope = CoroutineScope(Dispatchers.Main + Job())
fun startWork() {
scope.launch {
delay(2000)
println("任务完成")
}
}
fun cancelWork() {
scope.cancel() // 取消所有任务
}
6.supervisorScope
supervisorScope
函数用于创建一个使用了 SupervisorJob 的 coroutineScope,该作用域的特点就是抛出的异常不会连锁取消同级协程和父协程
fun main() = runBlocking {
launch {
delay(100)
log("Task from runBlocking")
}
supervisorScope {
launch {
delay(500)
log("Task throw Exception")
throw Exception("failed")
}
launch {
delay(600)
log("Task from nested launch")
}
}
log("Coroutine scope is over")
}
结果打印
[main] Task from runBlocking
[main] Task throw Exception
[main] Task from nested launch
[main] Coroutine scope is over