【EventBus】EventBus 源码解析 ( 事件发送 | EventBus.post 方法 | EventBus.postSingleEvent 方法 )
2023-06-13 09:17:57 时间
文章目录
一、EventBus 事件发送
在客户端的某个线程中 , 调用 EventBus.getDefault().post("Hello EventBus !");
方法 , 向消息中心发送消息 ;
在 EventBus
中 , 获取 ThreadLocal
数据 PostingThreadState
, 其中记录了 线程状态信息 , 其中维护了一个事件队列 List<Object> eventQueue
, 将本次传入的事件 , 加入到该事件队列中 ;
然后判断发布线程是否是主线程 , 并保存发送状态 ;
// 判断是否处于主线程
postingState.isMainThread = isMainThread();
// 保存临时状态 , 放置重复调用
postingState.isPosting = true;
EventBus.post 方法源码 :
/**
* EventBus是Java和Android的中央发布/订阅事件系统。
* 事件被发布({@link#post(Object)})到总线,总线将其传递给具有匹配处理程序的订阅者
* 事件类型的方法。
* 要接收事件,订阅者必须使用{@link#register(Object)}将自己注册到总线。
* 一旦注册,订阅服务器将接收事件,直到调用{@link#unregister(Object)}。
* 事件处理方法必须由{@link Subscribe}注释,必须是公共的,不返回任何内容(void),
* 并且只有一个参数(事件)。
*/
public class EventBus {
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
/** 将给定的事件传递给事件总线 */
public void post(Object event) {
// ThreadLocal 数据
// ThreadLocal<PostingThreadState> currentPostingThreadState
// PostingThreadState 可以理解成一个辅助类
PostingThreadState postingState = currentPostingThreadState.get();
// 该队列用于维护事件 , 是一个事件队列 , 队列的固有属性就是 先进先出
List<Object> eventQueue = postingState.eventQueue;
// 将传入事件加入到队列中
eventQueue.add(event);
if (!postingState.isPosting) {
// 判断是否处于主线程
postingState.isMainThread = isMainThread();
// 保存临时状态 , 放置重复调用
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
// 发送单个事件 , 该方法是核心调用方法
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
}
二、事件发送 postSingleEvent 方法
首先 , 获取发送的事件类型 ;
// 获取发送的消息事件类型
Class<?> eventClass = event.getClass();
然后通过 eventInheritance
变量 , 判断是否支持事件类型的父类查找 , 该值默认为 true ;
// 判断事件类型的父类 , 向事件的上一级类型查找
// 传入的是否是某个事件的父类对象
// 该值默认为 true
if (eventInheritance) {
如果支持事件类型父类查找 , 则获取当前所有的事件类型集合 , 进行单个事件的发送 ;
// 获取当前所有的 事件类型 集合
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
// 进行单个事件的发送
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
EventBus.postSingleEvent 方法源码 :
public class EventBus {
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
// 获取发送的消息事件类型
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
// 判断事件类型的父类 , 向事件的上一级类型查找
// 传入的是否是某个事件的父类对象
// 该值默认为 true
if (eventInheritance) {
// 获取当前所有的 事件类型 集合
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
// 进行单个事件的发送
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
}
相关文章
- 8.19VR行业大事件:扎克伯格的最新虚拟化身遭群嘲;联想拯救者VR700首发价2999元
- 【Qt】Qt 开发桌面程序 ( Qt 版本 5.14.2 | 编辑 Qt 桌面按钮控件 | 修改按钮文本 | 为按钮添加点击事件 | 系统调用 | 去掉系统调用命令窗口 )
- 【Kotlin 协程】协程中的多路复用技术 ② ( select 函数原型 | SelectClauseN 事件 | 查看挂起函数是否支持 select )
- Oracle 等待事件 ASYNC Remote Write 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 cursor: pin X 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 log file switch (private strand flush incomplete) 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 virtual circuit wait 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:KK,RedoLog”Kick” 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:TE,ExtendTable 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:TS,TemporarySegment(alsoTableSpace) 官方解释,作用,如何使用及优化方法
- Table Control 响应双击事件详解编程语言
- JS removeEventListener()和detachEvent()方法:销毁事件
- JS事件流(冒泡型+捕获型+混合型)
- 美拟议《网络事件通报法案》将赋予信息披露企业部分豁免权
- MySQL记录被锁:事件爆发及解决之道(mysql记录被锁)
- 吴亦凡事件之后 明星维权不发律师函选择报警合适吗?
- MySQL事件调度器:自动化运行任务(mysql的事件调度器)
- 解决方法MySQL建立事件失败,如何解决(mysql不能建事件)
- JavaScriptEvent学习第三章早期的事件处理程序
- JS中动态添加事件(绑定事件)的代码
- js修改table中Td的值(定义td的双击事件)
- windowresize和scroll事件的基本优化思路
- js判断手机和pc端选择不同执行事件的方法
- jQuery级联操作绑定事件实例