协程
教学网站
- https://www.bennyhuo.com/book/kotlin-coroutines/
教学视频
- https://space.bilibili.com/28615855/channel/collectiondetail?sid=375593
- https://www.bilibili.com/video/BV1uo4y1y7ZF?spm_id_from=333.337.search-card.all.click
教学书籍
深入理解kotlin协程
协程作用域:
它会跟踪所有协程,同样他也可以取消由他启动的所有协程。
GlobalScope
: 生命周期是process级别的,即使Activity或Fragment已经被销毁,协程仍然在执行。MainScope
: 在Activity 中使用,可以在onDestory中取消协程。viewModelScope
: 只能在ViewModel中使用,绑定viewModel的生命周期lifeCycleScope
: 只能在Activity, Fragment中使用,绑定Activity, Fragment的生命周期
协程构建器
launch
:返回一个job并且不附带任何结果。async
:返回一个Deferred, Deferredy也是一个job可以使用await()在一个延期的值上得到他的最终结果。
协程作用域构建器
coroutineScope
: 一个协程失败了,其他的所有兄弟协程也会被取消。supervisorScope
: 一个协程失败了,不会影响其他兄弟协程。
协程的取消
- 取消作用域会取消他的子协程。
- 被取消的子协程并不会影响其余兄弟协程。
- 协程通过抛出一个特殊的异常CancellationException来处理取消操作。
- 所有kotlin.coroutines中的挂起函数(withContext, delay等)都是可以取消的。
Cpu密集任务协程取消
- isActive是一个可以被使用在CoroutineScope中的扩展属性,检查job是否处于活跃状态。
- ensureActive(), 如果job处于非活跃的状态,这个方法会立即抛出异常。
- yield函数会检查所在协程的状态,如果已经取消,则抛出CancellException予以响应。此外,它还会尝试出让线程的执行权,给其他协程提供执行的机会。
协程启动模式
DEFAULT
: 协程创建后,立即开始调度,在调度前如果协程被取消,其将进入取消响应状态。ATOMIC
: 协程创建后,立即开始调度,协程执行到第一个挂起点之前协程不能被取消。LAZY
: 只有协程被需要时,包括主协程调用协程的start, join或者await等函数时才会开始调度,如果调度前就被取消,那么协程将直接进入异常结束状态。UNDISPATCHED
: 协程创建后立即在当前函数调用栈中执行,知道遇到第一个真正的挂起点。
注意事项:
- 创建协程作用域的时候要加supervisor() ,防止一个协程失败导致其他协程也失败。
1
| val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
- 在协程的finally 要做必须的事情的时候要在NonCancellable协程上下文做。
1
2
3
4
5
6
7
8
| viewModelScope.launch {
try {
} catch (e: IOException)
withContext(NonCancellable) {
}
}
|
- 不要try Catch所有的Exception,会导致协程不能取消。
1
2
3
4
5
6
7
| viewModelScope.launch {
try {
} catch (e: Exception) {
if (e is CancellationException) throw e
}
}
|
- 要将Dispatcher 注入,不要写明使用哪个。
- 内置的suspend 函数才会响应cancellException,所以写文件时需要自己调用ensureActive()或者yield()。
1
2
3
4
5
6
7
| viewModelScope.launch {
try {
ensureActive()
} catch (e: Exception) {
if (e is CancellationException) throw e
}
}
|