android 粘性弹窗,android组件化通信之EventBus粘性事件解析
背景
最近项目做组件化,需要进行组件化的通信,有时候可能会出现异步的情况,事件接收方还没准备好事件就已经发送过来了。这时候想到了EventBus的粘性事件。什么是粘性事件呢,通俗点讲就是不达目的不罢休的事件,事件保证能发送到订阅者手里。
发送粘性事件
EventBus发送粘性事件非常简单,一段代码就可以搞定:
EventBus.getDefault().postSticky(event)
接收粘性事件
接收粘性事件也非常简单,注册方法上加个sticky = true即可
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void loginSuccessEvent(event: LoginSuccessEvent){}
粘性事件代码解析
一行代码就能实现这件神奇的事情,那么中间到底发生了什么呢,下面我们分析下源码:
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
从代码中发现首先会把粘性事件用stickyEvents缓存起来,然后像普通事件一样post出去。
stickyEvents是一个Map集合,加入这个集合里面会发生什么呢?
private final Map, Object> stickyEvents;
通过跟踪我们会发现以下代码
public void register(Object subscriber) {
Class> subscriberClass = subscriber.getClass();
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
....省略N段代码...
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, Object> entry : entries) {
Class> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
从上面可以看出在register事件的时候回调用subscribe方法,在subscribe中会处理stickyEvents中的粘性事件通过checkPostStickyEventToSubscription方法发送出去,继续跟踪发现最终都会走到下面这个方法里面
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
subscription.subscriberMethod.method.invoke(subscription.subscriber, event)就是执行在订阅者那边定义的处理事件的方法,至此整个流程就结束了。
看到这里想必大家都发现了,粘性事件有可能会收到两次,注意我这里用的是有可能。
让我们分析以下两种场景:
第一种订阅者Activity已经启动了,这时候事件通过postSticky之后调用post发送,而stickyEvents中缓存的事件不会发送,这是为什么呢。前面分析stickyEvents中事件的处理是在事件register的时候,而这时候粘性事件还没有发送所以只会发送一次。
第二种订阅者Activity还没启动但是粘性事件发送了,这时候通过post方式发送的消息是收不到的,然后当订阅者Activity中register事件时就会再发送一遍粘性事件。
综述,最终事件只会发送一遍。
android 粘性弹窗,android组件化通信之EventBus粘性事件解析相关推荐
- vue组件化通信之兄弟组件传值
vue组件化通信之父向子传值 vue组件化通信之子向父传值 在vue中兄弟节点传值一般有两种方法:$parent和 $root, 建议使用前者 使用$parent **parent.vue** < ...
- vue组件化通信之子向父传值
vue组件化通信之子向父传值 vue组件化通信之兄弟组件传值 vue中子向父传递消息一般使用$emit,方法比较简单,直接看代码 父组件 <template><div>< ...
- vue组件化通信之父向子传值
vue组件化通信之子向父传值 vue组件化通信之兄弟组件传值 父向子组件传值 常用的方法主要有三种:props.$refs.$children 建议使用前两种 使用props进行传值 parent.v ...
- Vue 组件化通信 provide inject ,dispatch ,boardcast
入门 作为前端最容易上手的框架,Vue入门其实没啥说的,我放一段清单的代码,大家能看懂就说明能上手了 <template><div id="app">< ...
- Android热更新,android组件化通信
2.集成SDK gradle这个配置 在app module的"build.gradle"文件中添加(示例配置): android { defaultConfig { ndk { ...
- Android 基于注解IOC组件化/模块化的架构实践
当前参与的项目历史也很久远,第一行代码据说是写于2014年的某一天,那时Android用的ide还是Eclipse.那时Android还没有很好的架构指导(mvp.mvvm).那时Android最新的 ...
- android 电商app组件化,APICloud AVM多端开发案例深度解析(一)--生鲜电商app开发
AVM多端开发是APICloud定义的一套新的代码编写标准(DSL):基于标准Web Components组件化思想,兼容Vue / React语法特性,通过一次编码,分别编译为Android和iOS ...
- Android:项目模块化/组件化的架构之路(一)
文章目录 前言 推荐 模块化需要做什么 一.如何拆分项目 二.模块之间的通信 1. 常用的通信方式 2. 改善通信方式 2.1 使用接口进行通信 2.2 如何对外暴露接口 2.3 使用EventBus ...
- android注册弹窗,Android开发之PopupWindow创建弹窗、对话框的方法详解
本文实例讲述了Android开发之PopupWindow创建弹窗.对话框的方法.分享给大家供大家参考,具体如下: 简介: PopupWindow 可创建类似对话框风格的窗口 效果: 使用方法: 使用P ...
最新文章
- Linux服务器---安装tftp-server
- 双系统gazebo闪退_记录Ubuntu16.04下PX4联合Gazebo仿真时遇到的问题与解决方法
- Oracle可以处理LOB字段的常用字符函数
- python计算每月工资-[Python] 2018新税法下工资计算
- 大数据WEB阶段Spring框架(四)Spring-MVC
- 【转】x.509证书在WCF中的应用(CS篇)
- Java设计模式笔记(6)观察者模式
- vmware挂载san存储_细述企业级存储NAS和SAN差异
- linux中进程的用户管理
- SQL2005存储过程解密
- Python单例模式的4种实现方法(转)
- Netty工作笔记0031---NIO零拷贝应用案例
- 二级mysql与access数据库_2017计算机二级Access数据库基础教程
- 01 分布式系统架构的冰与火
- Ftp搜索引擎开发实践
- linux 筛选重复数据,Linux下uniq筛选
- keep行走和计步_KEEP跑步计步器
- 股票自动交易接口简化
- maven安装及环境部署(IDEA)
- 2021.11.25 小组加分制度的破绽
热门文章
- 计算机二级python 公共基础题总结
- 2106 Problem F Shuffling Along
- MICK-SQL基础教程(第二版)第七章 集合运算
- 微信支付 回调地址哪里设置
- tomcat项目部署到本地局域网访问
- 2018世界机器人大会来了
- java数据结构YZP专栏-----链表
- Linux搭建MonggoDB环境
- 梦幻诛仙 修改服务器时间,《梦幻诛仙手游》2019年3月12日14:00~19:00数据互通公告...
- url 转义 java_Java 特殊字符URL转义 | 学步园