概念
- 协程:本质就是线程框架。一套基于 Thread(线程) 封装的 工具API(就像 Java 的 Executor 、Android 的 AsyncTask Handler 以及 RxJava)。
- 挂起函数:
- 挂起的本质:切线程执行完后会自动切回来继续。
- 挂起函数挂起的是当前在执行的协程,然后执行自己的协程。此时被挂起的协程和执行它的线程会分离,线程继续去执行其他任务或无事可干(就是它原本的样子,回收或再利用),当挂起函数执行完会切回来继续执行之前被挂起的协程(之前的线程拿到异步的结果继续执行)。
- 由于消除了回调嵌套可以自定义挂起函数:
- 什么时候定义:需要做耗时操作的时候(I/O、计算、等待)才会挂起当前的协程。
- 解决了什么:创建者告知这是一个耗时操作,并指定了该协程在后台线程执行,保障了调用者的线程安全。
- suspend 关键字:用来限制该函数只能在协程里调用或者在其他挂起函数里调用,因为“挂起->执行完->切回去”只有在协程中使用才能实现。真正挂起操作靠的是最终调用的那个协程自带的挂起函数。也有提醒“这是一个耗时操作,是挂起函数要在协程中使用”的意思。
- 非阻塞式:本质就是不卡线程。对比其他基于 Java 的多线程解决方案,协程的优点是借助 Kotlin 语言的优势,让我们方便在同一代码块(作用域)里做线程切换(同时启动N个协程运行在不同线程,让看起来同步的方式写出异步代码),即原先串行写的代码现在并行来写(同一代码块里的代码是在同一线程执行(单线程是阻塞式的,当前任务没做完就不会执行后面的代码,切到别的线程处理就不会卡之前的线程),Java切线程会回调里嵌套回调关系复杂,而每个协程执行在自己指定的线程中(创建时通过Dispatchers调度,而不是Thread因为不是单纯指定线程),消除回调让多个协程上下连续写在同一代码块里,逻辑直观并消除模板代码),消除多线程异步之间协作任务的操作难度。
协程作用域 CoroutineScope
用来启动协程,并对它们进行统一管理(挂起和恢复)。
- GlobalScope 类:全局协程作用域。通过它启动的协程可以一直运行到应用停止。不会阻塞其所在线程,启动的协程相当于守护线程,不会阻止JVM结束运行。可能会导致内存泄漏慎用。
- runBlocking 顶层函数:阻塞式协程作用域。会阻塞当前线程直到其内部所有协程执行完毕,内部的协程彼此之间依旧是非阻式,参数二的函数接收者为CoroutineScope,因此可以在函数内部启动协程。
- coroutineScope:
- supervisorScope:
- 自定义:可用于主动控制协程的生命周期,对Android开发意义在于避免内存泄漏,见后文的 ViewModelKTX、LifeCycleKTX。
协程上下文 CoroutineContext
协程创建 CoroutineBuilder
挂起函数 Suspend Function
| suspend | 挂起当前协程,并保存它的状态(变量)。只能有协程或其他挂起函数调用。 |
| resume | 返回到上一个挂起的协程,并从之前的状态中恢复执行。 |
ViewModelKTX
LifeCycleKTX