请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

请教个问题 createCoroutineUnintercepted

//kotlinx.coroutines.Builders.common.kt
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
}

上面的已经创建了协程了,但是在 coroutine.start 里面,我一路跟到 CoroutineStart 中:

   /**
    * Starts the corresponding block as a coroutine with this coroutine's start strategy.
    *
    * * [DEFAULT] uses [startCoroutineCancellable].
    * * [ATOMIC] uses [startCoroutine].
    * * [UNDISPATCHED] uses [startCoroutineUndispatched].
    * * [LAZY] does nothing.
    *
    * @suppress **This an internal API and should not be used from general code.**
    */
   @InternalCoroutinesApi
   public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>) =
       when (this) {
           CoroutineStart.DEFAULT -> block.startCoroutineCancellable(completion)
           CoroutineStart.ATOMIC -> block.startCoroutine(completion) // 进入这里
           CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(completion)
           CoroutineStart.LAZY -> Unit // will start lazily
       }

然后进入 block.startCoroutine:

/**
 * Starts a coroutine without a receiver and with result type [T].
 * This function creates and starts a new, fresh instance of suspendable computation every time it is invoked.
 * The [completion] continuation is invoked when the coroutine completes with a result or an exception.
 */
@SinceKotlin("1.3")
@Suppress("UNCHECKED_CAST")
public fun <T> (suspend () -> T).startCoroutine(completion: Continuation<T>) {
    createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

这里的 createCoroutineUnintercepted 又是在创建协程,completion 实际上就是上面 launch 中创建的协程了。

1、这个 createCoroutineUnintercepted 为啥又创建一边??

2、createCoroutineUnintercepted 的源码在哪里?

正在回答 回答被采纳积分+3

4回答

提问者 xxxxjase 2020-10-07 00:13:29



下面是一个 launch 中创建的协程:

val coroutine = if (start.isLazy) // 这里创建了协程
       LazyStandaloneCoroutine(newContext, block) else
       StandaloneCoroutine(newContext, active = true) 里面创建的协程也是一个 Continuation 对象

suspend lambda 通过编译器处理后,会生成一个 SuspendLambda 类

继承关系如下:SuspendLambda -> ContinuationImpl -> BaseContinuationImpl : Continuation<Any?>

可以看到,还是一个 Continuation 对象;

然后会将上面的 Continuation 对象作为构造器的参数,然后创建 suspend lambda 对应的。

我的理解是下面的这个 Continuation 是 launch 中的那个 Continuation 的包装了一层;


0 回复 有任何疑惑可以回复我~
  • launch里new出来的是completion。你仔细看看。
    回复 有任何疑惑可以回复我~ 2020-10-07 11:17:55
提问者 xxxxjase 2020-10-06 18:16:05

CoroutineScope.launch 方法里面已经创建了协程:Coroutine

val coroutine = if (start.isLazy) // 这里创建了协程
       LazyStandaloneCoroutine(newContext, block) else
       StandaloneCoroutine(newContext, active = true)

那为啥还要 createCoroutineUnintercepted?? 这两个是什么关系呢??不得骑姐。。






0 回复 有任何疑惑可以回复我~
  • 这是官方文档最暧昧的地方。你如果看过我的书,你会发现我为了做这个区分,把前面通过上层API创建出来的“协程”称为“复合协程”,把后面通过标准库的 api 创建出来的“协程”叫做“简单协程”。
    
    launch 启动的“协程”是从我们业务开发的角度来看的,本质上对 createCoroutineUnintercepted 启动的“协程”是一种封装,提供了更多的能力,例如运行状态,异常传递,作用域,取消响应等等。createCoroutineUnintercepted 创建的则是一个最最基本的协程。
    回复 有任何疑惑可以回复我~ 2020-10-06 18:22:37
  • 提问者 xxxxjase 回复 bennyhuo #2
    也就是说 val coroutine = if (start.isLazy) // 这里创建了协程
            LazyStandaloneCoroutine(newContext, block) else
            StandaloneCoroutine(newContext, active = true)
    
    是上层的协程了??偏向于业务,而 createCoroutineUnintercepted 是核心的最基本的协程了??二者会通过组合的协同在一起??我的理解。
    回复 有任何疑惑可以回复我~ 2020-10-06 18:40:35
  • 提问者 xxxxjase 回复 bennyhuo #3
    还有你的书叫啥名字??=。=
    回复 有任何疑惑可以回复我~ 2020-10-06 18:41:01
bennyhuo 2020-10-06 17:01:29

更正:

回复里面同学在 Jvm 里面找到了这个函数的实现。我确认了一下哈,后来的 Kotlin 标准库的源码有些变化,createCoroutineUnintercepted 函数现在提供了实现,不过常规的情况下还是会走到下面的 create 函数调用,这个函数仍然是需要编译器通过传入的 Lambda 表达式来生成的哈。

Kotlin 协程这几年的源码变动确实比较大,类似的还有最早的时候 Continuation 的 resume和 resumeWithException 还是它的函数,后来就成了扩展函数等等。大家在学习时,以源码为准~

---

createCoroutineUnintercepted 这个函数的源码是没有的,编译器编译时会生成一些字节码,也就是编译器会基于参数lambda表达式生成一个SuspendLambda的类,这个点咱们视频里面有提到哈。

0 回复 有任何疑惑可以回复我~
  • 提问者 xxxxjase #1
    你瞎说,我刚刚都找到了=。=:
    
    @SinceKotlin("1.3")
    public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
        completion: Continuation<T>
    ): Continuation<Unit> {
        val probeCompletion = probeCoroutineCreated(completion)
        return if (this is BaseContinuationImpl)
            create(probeCompletion)
        else
            createCoroutineFromSuspendFunction(probeCompletion) {
                (this as Function1<Continuation<T>, Any?>).invoke(it)
            }
    }
    回复 有任何疑惑可以回复我~ 2020-10-06 17:11:19
  • 提问者 xxxxjase #2
    这个是一个跨平台类,在 kotlin-stdlib.jar 里面 kotlin.coroutines.intrinsics.IntrinsicsJvm 里面=。= 我找了好久。。。
    回复 有任何疑惑可以回复我~ 2020-10-06 17:13:34
  • bennyhuo 回复 提问者 xxxxjase #3
    害,我看错了,你看下这个函数里面的源码,肯定最终会调用到一个没有实现的函数的
    回复 有任何疑惑可以回复我~ 2020-10-06 17:18:20
bennyhuo 2020-10-06 16:59:00

这是官方的源码哈。
createCoroutineUnintercepted 是创建协程最终要调用到的代码,所有创建协程的api其实都是对它的封装。

0 回复 有任何疑惑可以回复我~

相似问题

登录后可查看更多问答,登录/注册

问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信