## 協程的取消需要內部配合
單純的執行`job.cancel()`是無法取消當前執行的協程,就像無法取消正在執行過程中的線程;
```kotlin
fun main() = runBlocking {
val job = launch(Dispatchers.Default) {
var i = 0
// 變化在這里,只有協程處于活躍狀態的時候,才會繼續執行循環內部的代碼
while (isActive) {
Thread.sleep(500L)
i++
println("i = $i")
}
}
delay(2000L)
job.cancel()
job.join()
println("End")
}
```
## 不要輕易打破協程的父子結構
下面代碼中`firstJob`無法通過`parentJob.cancel`被取消,因為`firstJob`設置了自己的`Job()`對象,并沒有關聯`parentJob`,打破了其協程的父子結構;
```kotlin
fun main2() = runBlocking {
val parentJob = launch(Dispatchers.IO) {
val firstJob = launch(Job()) {
var i = 0
while (isActive) {
Thread.sleep(500L)
i++
println("First i = ${i}")
}
}
val secondJob = launch {
var i = 0
while (isActive) {
Thread.sleep(500L)
i++
println("Second i = ${i}")
}
}
}
delay(2000L)
parentJob.cancel()
parentJob.join()
println("End")
Thread.sleep(100_000)
}
```
## 捕獲CancellationException以后,要考慮是否應該重新拋出來
```kotlin
fun main() = runBlocking {
val parentJob = launch(Dispatchers.IO) {
launch() {
var i = 0
while (true) {
try {
delay(500L)
} catch (e: CancellationException) {
// 這里如果不將CancellationException拋出,那么該協程被取消也不會結束
e.printStackTrace()
}
i++
println("First i = ${i}")
}
}
launch {
var i = 0
while (true) {
delay(500L)
i++
println("Second i = ${i}")
}
}
}
delay(2000L)
parentJob.cancel()
parentJob.join()
println("End")
Thread.sleep(100_000)
}
```
## 不要直接使用try-catch直接包裹launch、async
使用`launch`和`async`啟動的協程其實已經是一個封閉的任務,任務內部有自己的異常處理邏輯,再外部進行`try-catch`是無法得到響應的內部異常的,只能捕獲到創建協程時候的異常;
## 靈活使用SupervisorJob,控制異常傳播范圍
`SupervisorJob`目前我只覺得只有當前協程拋出異常才能做到不影響子協程和父協程,如果是子協程拋出異常那么`SupervisorJob`也無能為力。因為創建子協程的時候又會創建一個新的`job`只不過其`parentjob`是`父協程的job`。
## 使用CoroutineExceptionHandler處理復雜結構的協程異常,它僅在頂層協程中起作用
- 寫在前面的話
- Java
- 基礎
- Double的比較
- 小數怎么用二進制表示
- 多線程
- 并發和并行
- 線程池
- 線程池背景
- 線程池構造
- 任務阻塞隊列
- Flutter
- 基礎知識
- Dart基礎
- Android
- 項目架構
- View
- 非UI線程更新View
- AlarmManager
- 對比postDelaryed和Timer
- Bitmap
- 加載100M的圖片卻不撐爆內存
- Bitmap壓縮
- Bitmap局部解碼
- 計算圖片的內存占用
- Android動畫
- Android動畫類型
- Android動畫原理
- 屬性動畫
- 幀動畫
- 補間動畫
- 使用動畫的注意事項
- Android新特性
- 權限組
- Android23(Marshmallow)-6.0
- Android24(Nougat)-7.0
- Android26(Oreo)-8.0
- Android28(Pie)-9.0
- Android29(Q)-10.0
- AndroidX遷移
- Kotlin
- 關鍵字
- Kotlin操作符
- CoroutineScope
- Flow
- CoroutineException