一、前言
之前简单的了解了下协程,但是协程还有很多东西,所以从本篇开始进行下系统的了解
二、添加依赖
在Android中使用协程,需要添加以下依赖:
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
三、Dispatch
协程主要有三部分组成,Job、CoroutineScope、Dispatcher。Job是每一个协程的句柄用来控制协程的生命周期。CoroutineScope是用来控制所有用它的launch
或者async
来创建的协程的生命周期。Dispatcher是用来对协程所处的线程进行调度。
Kotlin 协程使用调度程序确定哪些线程用于执行协程。要在主线程之外运行代码,可以让 Kotlin 协程在 Default 或 IO 调度程序上执行工作。在 Kotlin 中,所有协程都必须在调度程序中运行,即使它们在主线程上运行也是如此。协程可以自行挂起,而调度程序负责将其恢复。
Kotlin 提供了三个调度程序,以用于指定应在何处运行协程:
- Dispatchers.Main - 使用此调度程序可在 Android 主线程上运行协程。此调度程序只能用于与界面交互和执行快速工作。示例包括调用
suspend
函数,运行 Android 界面框架操作,以及更新LiveData
对象。 - Dispatchers.IO - 此调度程序经过了专门优化,适合在主线程之外执行磁盘或网络 I/O。示例包括使用 Room 组件、从文件中读取数据或向文件中写入数据,以及运行任何网络操作。
- Dispatchers.Default - 此调度程序经过了专门优化,适合在主线程之外执行占用大量 CPU 资源的工作。用例示例包括对列表排序和解析 JSON。
四、CoroutineScope
CoroutineScope负责不同协程之间的结构和父子关系。我们总是在一个范围内启动新的协程。 CoroutineContext存储用于运行给定协程的附加技术信息,例如协程自定义名称,或指定协程应在其上调度的线程的调度程序。
所有协程必须在CoroutineScope中创建。但是它并不运行协程。创建一个CoroutineScope方式如下:
class ExampleClass {
// Job and Dispatcher are combined into a CoroutineContext which
// will be discussed shortly
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun exampleMethod() {
// Starts a new coroutine within the scope
scope.launch {
// New coroutine that can call suspend functions
fetchDocs()
}
}
fun cleanUp() {
// Cancel the scope to cancel ongoing coroutines work
scope.cancel()
}
}
在Android中为协程做了很多拓展,例如viewModelScope
,所以实际上不需要如此麻烦的创建,除非自己有特殊需要。
五、Job
每一个协程都有一个Job,用于控制其单独的生命周期,如下
class ExampleClass {
...
fun exampleMethod() {
// Handle to the coroutine, you can control its lifecycle
val job = scope.launch {
// New coroutine
}
if (...) {
// Cancel the coroutine started above, this doesn't affect the scope
// this coroutine was launched in
job.cancel()
}
}
}
六、CoroutineContext
CoroutineContext
使用以下元素集定义协程的行为:
Job
:控制协程的生命周期。CoroutineDispatcher
:将工作分派到适当的线程。CoroutineName
:协程的名称,可用于调试。CoroutineExceptionHandler
:处理未捕获的异常。
对于在作用域内创建的新协程,系统会为新协程分配一个新的 Job
实例,而从包含作用域继承其他 CoroutineContext
元素。可以通过向 launch
或 async
函数传递新的 CoroutineContext
替换继承的元素。请注意,将 Job
传递给 launch
或 async
不会产生任何效果,因为系统始终会向新协程分配 Job
的新实例。
class ExampleClass {
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun exampleMethod() {
// Starts a new coroutine on Dispatchers.Main as it's the scope's default
val job1 = scope.launch {
// New coroutine with CoroutineName = "coroutine" (default)
}
// Starts a new coroutine on Dispatchers.Default
val job2 = scope.launch(Dispatchers.Default + "BackgroundCoroutine") {
// New coroutine with CoroutineName = "BackgroundCoroutine" (overridden)
}
}
}
三、参考链接
-
将 Kotlin 协程与架构组件一起使用
https://developer.android.google.cn/topic/libraries/architecture/coroutines
-
协程简介
https://developer.android.google.cn/codelabs/basic-android-kotlin-training-introduction-coroutines
-
Kotlin协程
-
协程
-
协程:第一件事
https://medium.com/androiddevelopers/coroutines-first-things-first-e6187bf3bb21