文章目录
- 什么是协程
- 协程的使用
- 创建&启动协程
- 协程调度
- 协程的优势
什么是协程
协程是一种并发设计模式,可以用来简化异步执行的代码。协程并没有抛弃线程机制自立门户,因为本质上协程在执行异步任务时也是通过线程池实现的,但是协程可以在线程间自由切换,相比于回调,协程更加简单。
协程的使用
协程最常用在并发的场景下,单线程中使用协程的总执行时间并不会比不用协程少。
创建&启动协程
函数的挂起与恢复
协程是在常规函数的基础上添加了两项操作,可以更优雅地处理耗时任务。在常规函数的invoke(或 call)和 return 之外,协程添加了suspend 和 resume:
- suspend:暂停执行当前协程,并保存所有局部变量。
- resume:用于已暂停的协程从暂停处恢复执行。
kotlin协程的挂起和恢复本质上就是函数的挂起与恢复。kotlin是如何做到的呢
启动协程的两种方式:
- launch: 可以启动新协程,不会将结果返回给调用方
- async: 可以启动新协程,并且允许使用await暂停函数返回结果
其中,launch函数不是顶层函数,并不能直接使用,可以通过下面三种方式来创建协程:
- runBlocking:runBlocking是顶层函数,可以直接来创建协程。不适用于开发中,因为是线程阻塞的,可以用来做单元测试
- GlobalScope:GlobalScope单例对象开启协程,生命周期和Application一致且不能取消,在Android中同样不推荐使用。
- CoroutineScope:自行通过CoroutineContext创建一个CoroutineScope对象,需要一个类型为CoroutineContext的参数,在Android中创建协程推荐使用这种方式。
协程调度
Kotlin 提供了三个调度程序,调度程序可用于指定协程执行在哪个线程中。在Kotlin中,所有的协程都必须在调度程序中执行:如协程需要执行在非主线程中,那么需要指定协程在Default或者IO调度程序上;如果协程需要执行在主线程,那么执行协程在Main调度程序上。下面是具体说明:
- Dispatchers.Main - 使用此调度程序可在 Android 主线程上运行协程。此调度程序只能用于与界面交互和执行快速工作。示例包括调用 suspend 函数、运行 Android 界面框架操作,以及更新 LiveData 对象。
- Dispatchers.IO - 此调度程序经过了专门优化,适合在主线程之外执行磁盘或网络 I/O。示例包括使用 Room 组件、从文件中读取数据或向文件中写入数据,以及运行任何网络操作。
- Dispatchers.Default - 此调度程序经过了专门优化,适合在主线程之外执行占用大量 CPU 资源的工作。用例示例包括对列表排序和解析 JSON。
协程的优势
设想一种场景,UI更新需要等待多个网络请求并行结束后执行,如果采用回调式写法,可能会既麻烦又别扭,而如果多个网络请求采用串行请求的话,那么耗时相比于并行将会大大增加;而如果使用协程,可以将多个并行请求以串行的方式编写,执行结果进行合并即可。
- 更安全的代码:kotlin中提供了许多语言功能,避免Java中最常见的null空指针等异常
- 语法简洁、富有表现力:相比于Java,kotlin可以使用更少的代码实现更多的功能。
- 可互操作:与Java语言无缝互通。即可以在kotlin代码中调用Java代码,同时也可以在Java代码中调用kotlin代码。kotlin代码本质上也是通过kotlin编译器编译后生成VM能识别的字节码。
- 结构化并发:使用看似阻塞式的写法来实现异步功能。相比于回调方式大幅简化了后台任务管理,例如网络请求、数据库访问等任务的管理。