协程中的自定义拦截器
Custom interceptors in coroutines
我已经熟悉协程的 ContinuationInterceptor
部分
我写了下面一段代码来验证我的想法
class MyContext: CoroutineContext.Element{
override val key : CoroutineContext.Key<*>
get() = object : CoroutineContext.Key<MyContext>{}
}
val myInterceptor = object : ContinuationInterceptor {
//Key is set to a non-interceptor type
override val key : CoroutineContext.Key<MyContext>
get() = object : CoroutineContext.Key<MyContext>{}
override fun <T> interceptContinuation(continuation:
Continuation<T>): Continuation<T> {
Log.i(TAG,"interceptor:"+continuation.context[CoroutineName].toString())
return Continuation(EmptyCoroutineContext) {
thread(name = "myThread") {
continuation.resumeWith(it)
}
}
}
}
lifecycleScope.launch(myInterceptor + CoroutineName("MY1")) {
Log.i(TAG,"MY1 start:"+Thread.currentThread().name)
fun1()
launch(CoroutineName("MY2")) {
Log.i(TAG,"MY2 run:"+Thread.currentThread().name)
}
withContext(Dispatchers.Main+CoroutineName("MY3")) {
Log.i(TAG,"MY3 run:"+Thread.currentThread().name)
}
Log.i(TAG,"MY1 end:"+Thread.currentThread().name)
}
我没有将 myInterceptor 键指定为 ContinuationInterceptor.Key
。
因此协程不应将其识别为拦截器。
MY1
和MY2
证明了这个想法,但是MY3
被myInterceptor
截获,在新的线程中运行。
我想知道:
为什么myInterceptor
被识别为拦截器
为什么 Dispatcher.Main
不起作用
所示代码的行为很奇怪。我找不到确切的原因。
我修复了您的代码中的一些明显问题,例如 return 每次都从 key
获取一个新对象,而不是实现 equals
。我 return 一个单身人士,所以默认 equals
有效:
class MyContext: CoroutineContext.Element {
companion object Key : CoroutineContext.Key<MyContext>
override val key: CoroutineContext.Key<MyContext> = Key
}
val myInterceptor = object : ContinuationInterceptor {
override val key: CoroutineContext.Key<MyContext> = MyContext.Key
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
println("interceptContinuation: ${continuation.context[CoroutineName]?.name}")
return Continuation(EmptyCoroutineContext) {
thread(name = "myThread") {
continuation.resumeWith(it)
}
}
}
override fun toString() = "My Interceptor"
}
不过,这些修复并没有改变行为,我们可以看到它甚至在扰乱调度之前就已经损坏了:
val goodCtx = CoroutineName("A") + CoroutineName("B")
val badCtx = myInterceptor + myInterceptor
println(goodCtx)
println(badCtx)
这会打印
CoroutineName(B)
[My Interceptor, My Interceptor]
第一行向您展示了行为应该是什么,第二行展示了您的实施情况。你打破了平等关系。我没明白为什么。
即使这个发现也不能直接解释为什么你的拦截器最终会被使用,但它确实能让你深入了解当你违背作者的意图使用框架时会发生什么样的事情。
我已经熟悉协程的 ContinuationInterceptor
部分
我写了下面一段代码来验证我的想法
class MyContext: CoroutineContext.Element{
override val key : CoroutineContext.Key<*>
get() = object : CoroutineContext.Key<MyContext>{}
}
val myInterceptor = object : ContinuationInterceptor {
//Key is set to a non-interceptor type
override val key : CoroutineContext.Key<MyContext>
get() = object : CoroutineContext.Key<MyContext>{}
override fun <T> interceptContinuation(continuation:
Continuation<T>): Continuation<T> {
Log.i(TAG,"interceptor:"+continuation.context[CoroutineName].toString())
return Continuation(EmptyCoroutineContext) {
thread(name = "myThread") {
continuation.resumeWith(it)
}
}
}
}
lifecycleScope.launch(myInterceptor + CoroutineName("MY1")) {
Log.i(TAG,"MY1 start:"+Thread.currentThread().name)
fun1()
launch(CoroutineName("MY2")) {
Log.i(TAG,"MY2 run:"+Thread.currentThread().name)
}
withContext(Dispatchers.Main+CoroutineName("MY3")) {
Log.i(TAG,"MY3 run:"+Thread.currentThread().name)
}
Log.i(TAG,"MY1 end:"+Thread.currentThread().name)
}
我没有将 myInterceptor 键指定为 ContinuationInterceptor.Key
。
因此协程不应将其识别为拦截器。
MY1
和MY2
证明了这个想法,但是MY3
被myInterceptor
截获,在新的线程中运行。
我想知道:
为什么
myInterceptor
被识别为拦截器为什么
Dispatcher.Main
不起作用
所示代码的行为很奇怪。我找不到确切的原因。
我修复了您的代码中的一些明显问题,例如 return 每次都从 key
获取一个新对象,而不是实现 equals
。我 return 一个单身人士,所以默认 equals
有效:
class MyContext: CoroutineContext.Element {
companion object Key : CoroutineContext.Key<MyContext>
override val key: CoroutineContext.Key<MyContext> = Key
}
val myInterceptor = object : ContinuationInterceptor {
override val key: CoroutineContext.Key<MyContext> = MyContext.Key
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
println("interceptContinuation: ${continuation.context[CoroutineName]?.name}")
return Continuation(EmptyCoroutineContext) {
thread(name = "myThread") {
continuation.resumeWith(it)
}
}
}
override fun toString() = "My Interceptor"
}
不过,这些修复并没有改变行为,我们可以看到它甚至在扰乱调度之前就已经损坏了:
val goodCtx = CoroutineName("A") + CoroutineName("B")
val badCtx = myInterceptor + myInterceptor
println(goodCtx)
println(badCtx)
这会打印
CoroutineName(B)
[My Interceptor, My Interceptor]
第一行向您展示了行为应该是什么,第二行展示了您的实施情况。你打破了平等关系。我没明白为什么。
即使这个发现也不能直接解释为什么你的拦截器最终会被使用,但它确实能让你深入了解当你违背作者的意图使用框架时会发生什么样的事情。