什么是协程
官方描述:协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。就像非常轻量级的线程。
为什么需要协程
- 轻量级
协程就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎是无代价的,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建任意个协程。
内存泄漏更少
使用结构化并发机制在一个作用域内执行多项操作。内置取消支持
取消操作会自动在整个协程层次内传播。jetpack集成
许多jetpack库都包含提供全面的协程支持扩展,某些库还提供自己的协程作用域。方便使用
如果后台执行一个复杂任务,第二个任务依赖上一个任务的执行结果,使用写成可以方便实现。这点类似于java8的Future以及Rxjava中的链式调用。
基础
gradle配置
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
- 挂起函数
suspend
修饰符修饰的函数是挂起函数。挂起函数挂起协程时,不会阻塞协程所在的线程。挂起函数执行完后恢复协程,后面的代码才能继续执行。挂起函数只能在协程中调用。
- CoroutineDispatcher
CoroutineDispatcher是协程调度器,决定协程运行的线程或线程池。
coroutines-core
中CoroutineDispatcher有三种标准实现:
Dispatchers.Default 指定线程为共有的线程池,线程数量最少为2最大为CPU数
Dispatchers.IO IO线程
Dispatchers.Main 主线程
Dispatchers.Unconfined 不指定线程
- 开启协程方法
开启方式比较 | 是否创建新协程 | 是否阻塞当前线程 | 是否指定协程调度器 | 是否有返回值 | 其他 |
---|---|---|---|---|---|
launch{} | 是 | 否 | 是 | 否 | |
async{} | 是 | 否 | 是 | 是 | 用await()获取返回值 |
runBlocking {} | 是 | 是 | 是 | 是 | 主要用于测试 |
withContext{} | 否 | 挂起协程不阻塞县城 | 是 | 是 | 可让您在不引入回调的情况下控制任何代码行的线程池,因此您可以将其应用于非常小的函数,例如从数据库中读取数据或执行网络请求。 |
- CoroutineScope
CoroutineScope 会跟踪它使用 launch 或 async 创建的所有协程。您可以随时调用 scope.cancel() 以取消正在进行的工作(即正在运行的协程)。不过,与调度程序不同,CoroutineScope 不运行协程。
- Job
Job 是协程的句柄。使用 launch 或 async 创建的每个协程都会返回一个 Job 实例,该实例是相应协程的唯一标识并管理其生命周期。