fix: 增加描述
This commit is contained in:
parent
0ede383062
commit
c160611e89
@ -37,14 +37,74 @@
|
||||
如上面代码所示,Kotlin中创建启动协程主要有3种方式:
|
||||
1. runBlocking - 启动一个阻塞式协程,协程体代码块内代码会阻塞所在线程,返回值为泛型T,就是在协程体内最后一行返回的数据类型
|
||||
2. launch - 启动一个非阻塞式协程,必须在协程作用域(CoroutineScope)内启动,但不会阻塞所在线程,返回值为Job
|
||||
3. async - 启动一个非阻塞式协程,必须在协程作用域(CoroutineScope)内启动,但不会阻塞所在线程,返回值为一个Deferred<T>,T泛型为协程体内最后一行返回的数据类型
|
||||
3. async - 启动一个非阻塞式协程,必须在协程作用域(CoroutineScope)内启动,但不会阻塞所在线程,返回值为一个Deferred<T>,T泛型为协程体内最后一行返回的数据类型。
|
||||
|
||||
- 协程的返回类型
|
||||
1. runBlocking的泛型返回值T
|
||||
runBlocking在默认情况下类似于一个封装好的方法,当然可以通过指定该方法运行的线程,让这个方法不阻塞主线程,这样就类似于我们在Java中的Thread,并且将run方法执行的结果最终返回回来,这里不做过多讨论。
|
||||
|
||||
2. launch的返回类型Job
|
||||
3. async的返回类型Deferred<T>
|
||||
2. launch的返回类型Job
|
||||
|
||||
Job我们可以认为他就是一个协程作业是通过CoroutineScope.launch生成的,同时它运行一个指定的代码块,并在该代码块完成时完成。我们可以通过isActive、isCompleted、isCancelled来获取到Job的当前状态
|
||||
|
||||
我们可以通过Job获取当前协程执行的状态,如下表所示,协程也存在对应的生命周期。
|
||||
|
||||
| State | [isActive] | [isCompleted] | [isCancelled] |
|
||||
| ----- | :--------: | :-----------: | :----------: |
|
||||
| New (optional initial state) | false | false | false |
|
||||
| Active (default initial state)| true | false | false |
|
||||
| Completing (transient state) | true | false | false |
|
||||
| Cancelling (transient state) | false| false | true |
|
||||
| Cancelled (final state) | false | true | true |
|
||||
| Completed (final state) | false |true| false |
|
||||
|
||||
3. async的返回类型Deferred<T>
|
||||
Deferred是继承自Job的,我们可以通过Deferred.await()方法获取协程的泛型T返回值。
|
||||
|
||||
## 0x12 详解协程参数
|
||||
上面的三种创建启动协程的方法,其构造方法内的参数都很类似。
|
||||
```Kotlin
|
||||
public fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T
|
||||
|
||||
public fun CoroutineScope.launch(
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
block: suspend CoroutineScope.() -> Unit
|
||||
): Job
|
||||
|
||||
public fun <T> CoroutineScope.async(
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
block: suspend CoroutineScope.() -> T
|
||||
):
|
||||
```
|
||||
可以看到,runBlocking相比其他两个方法,缺少了协程启动模式CoroutineStart类型的参数,三个方法参数都有协程下上文CoroutineContext和协程执行体CoroutineScope.()。接下来我们就主要了解这三个参数类型。
|
||||
|
||||
- 协程上下文CoroutineContext
|
||||
它是一个包含了用户定义的一些各种不同元素的Element对象集合。其中主要元素是Job、协程调度器CoroutineDispatcher、还有包含协程异常CoroutineExceptionHandler、拦截器ContinuationInterceptor、协程名CoroutineName等。这些数据都是和协程密切相关的,每一个Element都一个唯一key。
|
||||
|
||||
通过协程上下文,我们可以定义协程调度器、协程名称、协程的异常处理方式等等,而这些都可以通过协程上下文中的重载关键字来实现。
|
||||
|
||||
- 协程调度器CoroutineDispatcher
|
||||
如上文所述,协程调度器也实现了协程上下文的接口,协程调度器可以指定当前协程所在的线程。
|
||||
|
||||
Kotlin默认提供了4中类型的协程调度线程:
|
||||
- Default:默认调度器,CPU密集型任务调度器,适合处理后台计算。通常处理一些单纯的计算任务,或者执行时间较短任务。比如:Json的解析,数据计算等。
|
||||
- IO:IO调度器,,IO密集型任务调度器,适合执行IO相关操作。比如:网络处理,数据库操作,文件操作等。
|
||||
- Main:UI调度器, 即在主线程上执行,通常用于UI交互,刷新等。
|
||||
- Unconfined:非受限调度器,又或者称为“无所谓”调度器,不要求协程执行在特定线程上。
|
||||
|
||||
不指定调度器时,协程运行在Default默认调度器下,需要注意的是,Default调度器对应的线程并非为主线程。
|
||||
|
||||
- 协程启动模式
|
||||
CoroutineStart协程启动模式,是启动协程时需要传入的第二个参数。协程启动有4种
|
||||
- DEFAULT 默认启动模式,我们可以称之为饿汉启动模式,因为协程创建后立即开始调度,虽然是立即调度,单不是立即执行,有可能在执行前被取消。
|
||||
- LAZY 懒汉启动模式,启动后并不会有任何调度行为,直到我们需要它执行的时候才会产生调度。也就是说只有我们主动的调用Job的start、join或者await等函数时才会开始调度。
|
||||
- ATOMIC 一样也是在协程创建后立即开始调度,但是它和DEFAULT模式有一点不一样,通过ATOMIC模式启动的协程执行到第一个挂起点之前是不响应cancel 取消操作的,ATOMIC一定要涉及到协程挂起后cancel 取消操作的时候才有意义。
|
||||
- UNDISPATCHED 协程在这种模式下会直接开始在当前线程下执行,直到运行到第一个挂起点。这听起来有点像 ATOMIC,不同之处在于UNDISPATCHED是不经过任何调度器就开始执行的。当然遇到挂起点之后的执行,将取决于挂起点本身的逻辑和协程上下文中的调度器。
|
||||
|
||||
这里需要特别注意的是UNDISPATCHED,非调度启动模式,在这个模式下,协程会在父协程所在线程直接执行,直到挂起函数出现,如果指定了对应的调度器,则会切换到对应的线程执行。
|
||||
-
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user