Androdi kotlin Coroutines(协程)详解 (一)
Androdi kotlin Coroutines(协程)详解 (二)
Androdi kotlin Coroutines(协程)详解 (三)
Androdi kotlin Coroutines(协程)详解 (四)
Androdi kotlin Coroutines(协程)详解 (五)
Androdi kotlin Coroutines(协程)详解 (六)
四、 CoroutineContext协程上下文
协同程序的持久上下文。它是[Element]实例的索引集,是一些元素的集合。索引集是集和映射的混合。这个集合中的每个元素都有一个唯一的[键]。
内部代码如下:
@SinceKotlin("1.3")
public interface CoroutineContext {
public operator fun <E : Element> get(key: Key<E>): E?
public fun <R> fold(initial: R, operation: (R, Element) -> R): R
public operator fun plus(context: CoroutineContext): CoroutineContext = ...
public fun minusKey(key: Key<*>): CoroutineContext
public interface Key<E : Element>
public interface Element : CoroutineContext {
public val key: Key<*>
...
}
}
CoroutineContext 作为一个集合,它的元素就是源码中看到的 Element,每一个Element 都有一个 key,因此它可以作为元素出现,同时它也是 CoroutineContext 的子接口,因此也可以作为集合出现。几个重要的子类:
4.1 CoroutineContext.Element
CoroutineContext的一个元素。协同程序上下文的元素本身就是一个单例上下文。
4.2 ContinuationInterceptor 协程拦截器
是 Element 的子类,拦截对象是 Continuation
public interface ContinuationInterceptor : CoroutineContext.Element {
companion object Key : CoroutineContext.Key<ContinuationInterceptor>
public fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
...
}
4.3 CoroutineDispatcher 协程调度器
继承了类 AbstractCoroutineContextElement ,实现了 ContinuationInterceptor 接口,先拦截再调度。所以如果我们想要实现自己的调度器,继承这个类就可以了,不过通常我们都用现成的,它们定义在 Dispatchers 当中:
val Default: CoroutineDispatcher
val Main: MainCoroutineDispatcher
val Unconfined: CoroutineDispatcher
val IO: CoroutineDispatcher
JVM | |
---|---|
Dispatchers.IO | 线程池 |
Dispatchers.Main | UI线程,Android中的主线程 |
Dispatchers.Default | 默认执行线程,线程池 |
Dispatchers.Unconfined | 直接执行 |
Dispatchers.Main比如在Android中的实现,最终是在 AndroidDispatcherFactory 类中,源码如下:
internal class AndroidDispatcherFactory : MainDispatcherFactory {
override fun createDispatcher(allFactories: List<MainDispatcherFactory>) =
HandlerContext(Looper.getMainLooper().asHandler(async = true), "Main")
override fun hintOnError(): String? = "For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used"
override val loadPriority: Int
get() = Int.MAX_VALUE / 2
}