Coroutin Scope 手動管理
Prerequisites:
使用Coroutin Scope時機:
- 自訂Dispatchers
- 需要自訂錯誤處理
- 需要手動取消Scope下面的子協程
建立CoroutineScope
建立一個獨立CoroutineScope,並且自訂Dispatchers。
runBlocking的Scope作用域是BlockingCoroutine。
CoroutineScope下面有一個子協程,名字為job1。

Dispatchers設為預設Dispatchers.Default。
使用scope.launch{},建立子協程並啟動子協程。
1
2
3
4
5
6
7
8
@Test
fun coroutin07() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
val job1 = scope.launch {
delay(1000)
println("job1")
}
}
但執行完卻沒有任何結果,這是為什麼?
runBlocking協程與CoroutineScope,沒有父子關係,所以runBlocking協程執行完畢就結束,不會等待CoroutineScope下的job1子協程執行完。
delay暫停
增加一個delay(大於1000),因為CoroutineScope下的子協程執行時為1秒,要讓runBlocking暫停超過1秒,再結束runBlocking協程。
delay()參數要大於1000,等到scope執行完畢,runBlocking協程才能結束。
1
2
3
4
5
6
7
8
fun coroutin07() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
scope.launch {
delay(1000)
println("job1")
}
delay(2000)
}
job1
join 等待
runBlocking協程「等待」scope.job完成,runBlocking才能結束。
1
2
3
4
5
6
7
8
fun coroutin07() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
val job = scope.launch {
delay(1000)
println("job1")
}
job.join()
}
job1
有CoroutineScope 與 沒有CoroutineScope
| 特性 | 沒有 CoroutineScope launch{} | 有 CoroutineScope scope.launch{} |
| 父子關係 | 與 runBlocking 是父子 | 與 runBlocking 無父子關係 |
| join | 自動join() | 手動join() |
| Dispatchers | 繼承runBlocking預設的Dispatchers | 使用自訂Dispatchers |
join
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 沒有 Scope - 自動join
fun example1() = runBlocking {
launch {
delay(1000)
println("一定會執行") // runBlocking 會等待
}
// 自動等待所有子協程
}
// 有 Scope - 自己寫join()
fun example2() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
scope.launch {
delay(1000)
println("可能不會執行!") // 如果 runBlocking 先結束
}
// runBlocking 結束時不會等待 scope 中的協程
// 需自己寫join(),runBlocking才會等待。
}
CoroutineScope使用時機
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 場景 1: 需要自訂Dispatchers
fun processInBackground() {
val ioScope = CoroutineScope(Dispatchers.IO)
ioScope.launch {
// 在IO線程執行網路請求
}
}
// 場景 2: 長時間運行的後台任務
class MyService {
private val serviceScope = CoroutineScope(Dispatchers.Default)
fun start() {
serviceScope.launch {
while (isActive) {
// 長時間運行的任務
delay(5000)
}
}
}
fun stop() {
serviceScope.cancel() // 需要手動取消
}
}
// 場景 3: 在非協程環境中啟動協程
fun nonCoroutineFunction() {
val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
// 在Android主線程更新UI
}
}