Element> get(key: Key<E>): E? public interface Key<E : Element> public interface Element : CoroutineContext } It’s made of: • Job — controls the lifecycle of the coroutine. • CoroutineDispatcher — dispatches work to the appropriate thread. • CoroutineName — name of the coroutine. • CoroutineExceptionHandler — handles uncaught exceptions. 6 val job = context[Job]
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } 8
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } 9
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } 10
“Using the keyword expect you can define an API to be implemented on each platform.” For JVM public actual typealias Runnable = java.lang.Runnable “The implementation of an expected declaration is marked with the keyword actual.” 12
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } Let’s see some important CoroutineDispatcher 13
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } 20
: CoroutineContext.Key<ContinuationInterceptor> /** * Returns continuation that wraps the original [continuation], thus intercepting all resumptions. */ public fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> } 21
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true public abstract fun dispatch(context: CoroutineContext, block: Runnable) public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation) } 22
2. CoroutineDispatcher decides whether to dispatch or not 3. If yes, CoroutineDispatcher uses Executor to execute DispatchedTask, which is a Runnable 4. DispatchedTask set correct CoroutineContext and invokes resume() or resumeWithException() 29
keyword expect you can define an API to be implemented on each platform.” “The implementation of an expected declaration is marked with the keyword actual.” 38
override fun run() { try { val delegate = delegate as DispatchedContinuation<T> val continuation = delegate.continuation val context = continuation.context val state = takeState() withCoroutineContext(context, delegate.countOrElement) { val exception = getExceptionalResult(state) val job = if (resumeMode.isCancellableMode) context[Job] else null if (exception == null && job != null && !job.isActive) { val cause = job.getCancellationException() cancelResult(state, cause) continuation.resumeWithStackTrace(cause) } else { if (exception != null) continuation.resumeWithException(exception) 48