一、协程概念
协程是一种并发设计模式,用它来简化异步执行的代码。
优点:
- 轻量:协程可以挂起,比阻塞更省内存
- 减少内存泄漏
- 支持取消
- 支持Jatpack集成
二、CoroutineScope 协程作用域
- GlobalScope 全局的,一般不会释放,所以基本不要
- MainScope 需要自己 取消
- LifecycleScope 不需要关心取消,自动绑定Lifecycle生命周期了
- ViewModelScope 不需要关心取消,自动绑定ViewModel生命周期了
三、CoroutineScope.launch、CoroutineScope.async
不阻塞线程,在后台开启协程,默认立马执行- 区别:launch 返回是Job,async 返回是Deferred<T> ,可以调用await()等待获取结果
四、suspend(挂起) 函数特点
suspend函数,不阻塞线程必须在协程或者suspend函数里面执行要等suspend函数执行完成,代码才继续往下执行
五、suspend withContext 、suspend coroutineScope
- 属于suspend 函数,不阻塞线程
里面最后一行作为返回值,要等里面的代码执行完成,才继续往下执行- 区别:withContext可以设置作用域,coroutineScope不行
六、CoroutineStart - 启动模式
- CoroutineStart.DEFAULT: 协程创建后,立即开始调度,但 有可能在执行前被取消。在调度前如果协程被取消,其将直接进入取消响应的状态。
- CoroutineStart.ATOMIC : 协程创建后,立即开始调度, 协程执行到第一个挂起点之前不响应取消。其将调度和执行两个步骤合二为一,就像它的名字一样,其保证调度和执行是原子操作,因此协程也 一定会执行。
- CoroutineStart.LAZY : 只要协程被需要时(主动调用该协程的 start、 join、 await等函数时 ),才会开始调度,如果调度前就被取消,协程将直接进入异常结束状态。
- CoroutineStart.UNDISPATCHED : 协程创建后,立即在当前线程中执行,直到遇到第一个真正挂起的点。 是立即执行,因此协程 一定会执行
六、Dispatchers - 协程调度器
- Default: 默认调度器 ,适合处理后台计算,其是一个 CPU 密集型任务调度器
- IO: IO 调度器,适合执行 IO 相关操作,其是 IO 密集型任务调度器
- Main: UI 调度器,根据平台不同会被初始化为对应的 UI 线程的调度器, 例如在Android 平台上它会将协程调度到 UI 事件循环中执行,即通常在 主线程上执行。
- Unconfined:“无所谓“调度器,不要求协程执行在特定线程上。协程的调度器如果是 Unconfined, 那么它在挂起点恢复执行时会在恢复所在的线程上直接执行,当然, 如果嵌套创建以它为调度器的协程,那么这些协程会在启动时被调度到协程框架内部的事件循环上,以避免出现 StackOverflow。
七、协程使用
// 协程测试类
object CoroutineTest : CoroutineScope by MainScope() { // 代理类实现 协程作用域
// 协程测试
suspend fun coroutineTest() {
// 挂起函数,要等代码执行完,才往下执行
val job = launch(Dispatchers.IO, CoroutineStart.LAZY) {
// GlobalScope 顶级作用域 其它作用域取消,对其没有影响
GlobalScope.launch {
// ...
delay(1000)
}
val deferred = async(Dispatchers.IO) {
"async result"
}
// withContext 挂起方法要在 协程 或者 suspend方法 里面调用
val withContextRes = withContext(Dispatchers.Default) {
// ...
"withContext result"
}
// await 挂起方法 要在 协程 或者 suspend方法 里面调用
val asyncRes = deferred.await() // 挂起 获取结果
}
// CoroutineStart.LAZY 要调用 start 或者 await()方法后才执行
job.start()
// 取消并等待执行完成
job.cancelAndJoin()
}
}