原理篇(一)关键类的分析
上面简单的介绍了一些用法,但是具体的原理和特点,好像还不是很清楚,那么下面就来介绍一下,一些关键的类,流程和原理。
介绍的相关的原理基于这行代码:
fun coroTest() {
GlobalScope.launch {
delay(1000L)//Delays coroutine for a given time without blocking a thread and resumes it after a specified time
Log.i(CO_TAG, "launch ")
}
Log.i(CO_TAG, "----")
}
然后贴上 launch() 的源码:
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
CoroutineScope
源码分析
首先,launch() 是 CoroutineScope 的一个扩展函数,
CoroutineScope 简单来说,就是协程的作用范围,每一个 Coroutine Builder,例如 CoroutineScope.launch,都是 CoroutineScope 的扩展,并且继承了其 coroutineContext .
Corotine 提供了全局的 CoroutineScope 也就是 GlobalScope,简单看下其代码:
//CoroutineScope.kt 中
public object GlobalScope : CoroutineScope {
/**
* Returns [EmptyCoroutineContext].
*/
override val coroutineContext: CoroutineContext
get() = EmptyCoroutineContext
}
//EmptyCorotineContext in CorotineContextImpl.kt 文件中
public object EmptyCoroutineContext : CoroutineContext, Serializable {
private const val serialVersionUID: Long = 0
private fun readResolve(): Any = EmptyCoroutineContext
public override fun <E : Element> get(key: Key<E>): E? = null
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R = initial
public override fun plus(context: CoroutineContext): CoroutineContext = context
public override fun minusKey(key: Key<*>): CoroutineContext = this
public override fun hashCode(): Int = 0
public override fun toString(): String = "EmptyCoroutineContext"
}
简单来说,GlobalScope 没有绑定任何 job,它用于构建最顶级的 coroutines,这些协程的生命周期跟随这个 Application,并且在 Application 生命周期结束之前,不会被 cancel。
关键函数分析
CoroutinScope 主要包含了以下扩展函数:
actor | fun <E> CoroutineScope.actor( context: CoroutineContext = EmptyCoroutineContext, capacity: Int = 0, start: CoroutineStart = CoroutineStart.DEFAULT, onCompletion: CompletionHandler? = null, block: suspend ActorScope<E>.() -> Unit): SendChannel<E> Launches new coroutine that is receiving messages from its mailbox channel and returns a reference to its mailbox channel as a SendChannel. The resulting object can be used to send messages to this coroutine. |
---|---|
async | fun <T> CoroutineScope.async( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T): Deferred<T> Creates new coroutine and returns its future result as an implementation of Deferred. The running coroutine is cancelled when the resulting deferred is cancelled. |
broadcast | fun <E> CoroutineScope.broadcast( context: CoroutineContext = EmptyCoroutineContext, capacity: Int = 1, start: CoroutineStart = CoroutineStart.LAZY, onCompletion: CompletionHandler? = null, block: suspend ProducerScope<E>.() -> Unit): BroadcastChannel<E> Launches new coroutine to produce a stream of values by sending them to a broadcast channel and returns a reference to the coroutine as a BroadcastChannel. The resulting object can be used to subscribe to elements produced by this coroutine. |
cancel | fun CoroutineScope.cancel(): Unit Cancels this scope, including its job and all its children. Throws IllegalStateExceptionif the scope does not have a job in it. |
launch | fun CoroutineScope.launch( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit): Job Launches new coroutine without blocking current thread and returns a reference to the coroutine as a Job. The coroutine is cancelled when the resulting job is cancelled. |
newCoroutineContext | fun CoroutineScope.newCoroutineContext( context: CoroutineContext): CoroutineContext Creates context for the new coroutine. It installs Dispatchers.Default when no other dispatcher nor ContinuationInterceptor is specified, and adds optional support for debugging facilities (when turned on). |
plus | operator fun CoroutineScope.plus( context: CoroutineContext): CoroutineScope Adds the specified coroutine context to this scope, overriding existing elements in the current scope’s context with the corresponding keys. |
produce | fun <E> CoroutineScope.produce( context: CoroutineContext = EmptyCoroutineContext, capacity: Int = 0, block: suspend ProducerScope<E>.() -> Unit): ReceiveChannel<E> Launches new coroutine to produce a stream of values by sending them to a channel and returns a reference to the coroutine as a ReceiveChannel. This resulting object can be used to receive elements produced by this coroutine. |
- actor{} 会启动一个能够接收 Message 的 Coroutine,也就是 SendChannel.你可以通过SendChannel.send() 方法给其它协程发送消息或者结果,或者通过 SendChannel.offer() 发送消息,两者区别在于 offer() 在队列满的时候,会返回失败,而 send() 则不会。对应接收消息的是 ReceiveChannel。
- async{} 会启动一个新的协程,并且返回一个 Deferred(它是一个 future 的实现),你可以通过 Deferred.await() 异步获取