我已经阅读了诸如 ContinuationInterceptor 、 githhub 之类的文档,了解函数InterceptContinuation() 和releaseInterceptedContinuation()。然而,我很难理解它们在协程中的用法。
我熟悉延续和协程上下文(元素和键)、调度程序和协程的内部工作原理。有人可以向我解释这两个函数,让我能够完全掌握它们的操作吗?
这些函数的作用完全按照文档所述:它们让我们拦截所有注册的延续并替换或通常将它们包装到我们自己的延续中。
但是,是的,我知道,它的“真正”含义以及我们如何使用它更难理解。请看这个例子:
suspend fun main() {
val interceptor = object : ContinuationInterceptor {
override val key = ContinuationInterceptor
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
return object : Continuation<T> {
override val context = continuation.context
override fun resumeWith(result: Result<T>) {
println("Resuming a continuation")
continuation.resumeWith(result)
}
}
}
}
withContext(interceptor) {
println("Going to suspend")
delay(1000)
println("Resumed")
}
}
我们创建了一个拦截器,它包装所有延续并在恢复原始延续之前记录一条消息。结果是这样的:
Going to suspend
...
Resuming a continuation
Resumed
我不完全确定
interceptContinuation
何时被调用。通常是在我们暂停的时候,但这并不完全正确。我们可以假设协程机制使用的每个延续都会在某个时刻被拦截。
使用拦截器最显着的例子是调度程序。当我们挂起时,我们创建了一个延续,它只“知道”如何返回函数,重新创建其状态并开始执行。这样的延续直接恢复,它不理解线程等。然后调度程序拦截这样的延续并将其包装到自己的延续中,因此原始的延续是例如在适当的线程池中执行。releaseInterceptedContinuation
类似 - 它让我们在继续之后进行一些清理,并且不再需要我们的包装器。