深入理解Kotlin协程SafeCoroutine

博客仅作为个人学习使用,不定期更新,方便以后复习时能够快速拾回这段遗忘的知识。如果有读者无意间搜索到这篇文章,阅读后觉得对您有所帮助,希望能点个赞,感谢支持。

SafeCoroutine作用

SafeCoroutine在suspendCoroutine中创建,主要有两个作用。

  1. 保证suspendCoroutine的挂起点(也就是传入lambda的continuation参数)只会被resume一次
  2. 保证suspend lambda参数直接resume时,不对线程进行挂起

suspendCoroutine间接调用了suspendCoroutineUninterceptedOrReturn,通过设置传递给suspendCoroutineUninterceptedOrReturn的lambda返回值来设置当前线程是否挂起

suspendCoroutineUninterceptedOrReturn三步骤

步骤1

在这里插入图片描述

可以看到SafeContinuation构造器传入的是c.intercepted也就是被拦截器包裹后的Continuation,此处SafeContinuation作为代理使用的。

举个例子

在这里插入图片描述

此时c.intercepted()实际就是MyInterceptor,具体很简单就是获取Continuation上下文中的ContinuationInterceptor。

在这里插入图片描述

【注意】 result的初始值为UNDECIDED,后续会使用到它。

步骤2

在这里插入图片描述

此时的block其实是传入suspendCoroutine的lambda,此时可以看出使用suspendCoroutine传入的lambda的第一个参数实际上是一个SafeContinuation,当其调用resume时其实调用的是SafeContinuation的resumeWith,然后再间接调用其代理的continuation。

如果在传入suspendCoroutine的lambda中直接调用了resume(没有切换线程)

举个例子

在这里插入图片描述

此时直接调resume,会直接调用到SafeCoroutine的resumeWith

在这里插入图片描述

此时会直接调用将RESULT就会被设置成resume时传入的value,同步更新到SafeCoroutine的result字段。

步骤3

在这里插入图片描述

注意这个函数的返回值,这将直接决定这个线程是否会被挂起。

在这里插入图片描述

可以看到流程会走到这里,如果不返回COROUTINE_SUSPENDED则线程就不会被挂起。

如果当初没有在传入suspendCoroutine的lambda中直接调用了resume,而是切换了上下文则result会被设置为COROUTINE_SUSPENDED

举个例子

在这里插入图片描述

此时在第二步中没有调用resume,所以此时result还是初始值UNDECIDED,在第三步中会被设置为COROUTINE_SUSPENDED,此时子线程中执行resume时仍还是SafeCoroutine的resumeWith(晕的话回头再看看)

在这里插入图片描述

如果result被设置为COROUTINE_SUSPENDED时则会间接调用被代理的continuation。

定制suspendCoroutineUninterceptedOrReturn

所以可以看出我们可以绕过suspendCoroutine直接调用suspendCoroutineUninterceptedOrReturn拓展协程的能力了。如果直接调用suspendCoroutineUninterceptedOrReturn就可以多次重复调用resume了。

在这里插入图片描述

输出结果
在这里插入图片描述

注意此时返回值为COROUTINE_SUSPENDED,否则线程不会被挂起,最终会主动进行resume,总体上就多resume 1次,就会是4次Start Done组合了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值