当前位置: 首页 > news >正文

【Android】Kotlin.flow在主线程collect为什么不阻塞主线程?

一,问题

问题,若在Activity中启动一个协程,指定上下文Dispatcher在主线程,而collect又是挂起方法,为什么不会阻塞主线程?

class DemoMainActivity: FragmentActivity() {private val mShareFlow: MutableSharedFlow<String> = MutableSharedFlow(replay = 1, extraBufferCapacity = 0, onBufferOverflow = BufferOverflow.SUSPEND)override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {super.onCreate(savedInstanceState, persistentState)lifecycleScope.launch(Dispatchers.Main) {mShareFlow.collect {//等待mShareFlow.emit数据处理}}}
}

二,分析

kotlin协程存在挂起、恢复点,内部通过状态机管理各种挂起状态。这里的collect就是挂起点,

反编译DemoMainActivity,可以看到如下内容


...
public final class DemoMainActivity extends FragmentActivity {@NotNullprivate final MutableSharedFlow mShareFlow;public DemoMainActivity() {this.mShareFlow = SharedFlowKt.MutableSharedFlow(1, 0, BufferOverflow.SUSPEND);}public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {super.onCreate(savedInstanceState, persistentState);BuildersKt.launch$default((CoroutineScope)LifecycleOwnerKt.getLifecycleScope((LifecycleOwner)this), (CoroutineContext)Dispatchers.getMain(), (CoroutineStart)null, new Function2((Continuation)null) {int label;public final Object invokeSuspend(Object $result) {Object var2 = IntrinsicsKt.getCOROUTINE_SUSPENDED();switch (this.label) {case 0:ResultKt.throwOnFailure($result);MutableSharedFlow var10000 = DemoMainActivity.this.mShareFlow;FlowCollector var10001 = null.INSTANCE;Continuation var10002 = (Continuation)this;this.label = 1;if (var10000.collect(var10001, var10002) == var2) {return var2;}break;case 1:ResultKt.throwOnFailure($result);break;default:throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");}throw new KotlinNothingValueException();}public final Continuation create(Object value, Continuation $completion) {return (Continuation)(new <anonymous constructor>($completion));}public final Object invoke(CoroutineScope p1, Continuation p2) {return ((<undefinedtype>)this.create(p1, p2)).invokeSuspend(Unit.INSTANCE);}// $FF: synthetic method// $FF: bridge methodpublic Object invoke(Object p1, Object p2) {return this.invoke((CoroutineScope)p1, (Continuation)p2);}}, 2, (Object)null);}
}

以上,collect编译后放在了invokeSuspend回调中(case 0 状态点),这在协程resume时调用。我们写代码的时候看似同步逻辑,其实在编译后都是各种invokeSuspend回调,这就回答了为什么不阻塞主线程。

那么主线程如何执行这个suspend点?很简单,通过MainHandler,

BuildersKt.launch$default((CoroutineScope)LifecycleOwnerKt.getLifecycleScope((LifecycleOwner)this), (CoroutineContext)Dispatchers.getMain(), (CoroutineStart)null, new Function2((Continuation)null)

Dispatchers.getMain()指定了一个invokeSuspend处理线程,即主线程。这里通过工厂方法返回一个HandlerDispatcher,如下,

在dispatch通过handler#post执行block逻辑,如下

这样就能通过Android#Handler机制在主线程处理suspend状态点了。

三,最后

本文分析基于以下kotlin协程实现分析,请参考

【Android】kotlin协程实现原理-CSDN博客

http://www.dtcms.com/a/428078.html

相关文章:

  • 数据整合展示中心
  • 阜宁网站制作哪家好我公司想做网站
  • Spring IOC源码篇七 核心方法obtainFreshBeanFactory自定义标签
  • 在哪里找做网站的客户郴州网络营销
  • 产生式规则对人工智能中自然语言处理深层语义分析的影响与启示研究
  • 南宁专业网站开发潍坊市网站制作
  • 网站后台登录密码修改自己网站做问卷调查
  • 在命令提示符页面中用pip命令行安装Python第三方库的详细步骤
  • 杭州开发网站的公司网站默认中文字体
  • 深度解析Epoch:模型训练中的“时间与泛化“博弈
  • MySQL索引特性(重点)
  • 【有序数组去重】2022-11-25
  • 【11408学习记录】考研数学线性代数精讲:矩阵方程求解与秩的深度解析
  • 专业沈阳网站制作大数据公司排名
  • 做受视频网站现在流行什么语言建设网站
  • TDengine 时序函数 STATEDURATION 用户手册
  • Java-Spring入门指南(十二)SpringAop的三种实现方式
  • 网站在线统计代码cms开发框架
  • CometD 长轮询协议及在Salesforce中的应用
  • 企术建站网站收录查询主要由哪几个网站
  • 中小型网站建设与网络搭建教育机构加盟
  • 重庆职业能力建设投稿网站网站正能量免费推广软件晚上
  • LeetCode 114. 二叉树展开为链表
  • 网站性能优化电子商务网站建设与管理期末答案
  • 橙色网站设计手机社区网站模板
  • ns3 配置 Ubuntu × CLion
  • 大模型——长文拆解上下文工程落地策略与实践
  • 网站免费建站pixiv appdw如何在网站做弹窗
  • 分身宝 1.0.8 | 无限多开系统级分身~更稳定安全支持同时登录多个社交软件、游戏账号,互不干扰,操作简单便捷,一键切换
  • 网站服务器租用价格 贴吧磁力神器