我们继续来看EventBus
类,的另一个入口方法post()
//已省略部分代码
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
post() 方法首先从 currentPostingThreadState
对象中取了一个 PostingThreadState
,我们来看看这个 currentPostingThreadState 对象的创建代码。
private final ThreadLocal currentPostingThreadState = new
ThreadLocal() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
ThreadLocal
是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,而这段数据是不会与其他线程共享的。其内部原理是通过生成一个它包裹的泛型对象的数组,在不同的线程会有不同的数组索引值,通过这样就可以做到每个线程通过 get() 方法获取的时候,取到的只能是自己线程所对应的数据。 在 EventBus 中, ThreadLocal 所包裹的是一个 PostingThreadState
类,它仅仅是封装了一些事件发送中过程所需的数据。
final static class PostingThreadState {
//通过post方法参数传入的事件集合
final List eventQueue = new ArrayList();
boolean isPosting; //是否正在执行postSingleEvent()方法
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
回到 post()
方法,我们看到其核心代码是这句:
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
每次调用post()
的时候都会传入一个事件,这个事件会被加入到队列。而每次执行postSingleEvent()
都会从队列中取出一个事件,这样不停循环取出事件处理,直到队列全部取完。 再看 postSingleEvent() 方法
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
//获取到eventClass所有父类的集合
List clazz = eventTypes.get(h);
//左或右只要有一个为真则为真,并赋值给左
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
//参考sendNoSubscriberEvent注释
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
还记得 EventBusBuild 中的 eventInheritance
是做什么的吗?它表示一个子类事件能否响应父类的onEvent()
方法。 再往下看 lookupAllEventTypes()
它通过循环和递归一起用,将一个类的父类,接口,父类的接口,父类接口的父类,全部添加到全局静态变量 eventTypes
集合中。之所以用全局静态变量的好处在于用全局静态变量只需要将那耗时又复杂的循环+递归方法执行一次就够了,下次只需要通过 key:事件类名 来判断这个事件是否以及执行过 lookupAllEventTypes() 方法。
然后我们继续往下,看发送方法 postSingleEventForEventType()
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
CopyOnWriteArrayList subscriptions;
synchronized (this) {
//所有订阅了eventClass的事件集合
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
//回调subscription的响应方法
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
}
return false;
}
它首先通过这一句
subscriptions = subscriptionsByEventType.get(eventClass);
获取到所有订阅了 eventClass 的事件集合,之前有讲过, subscriptionsByEventType 是一个以 key:订阅的事件 value:订阅这个事件的所有订阅者集合 的 Map 。 最后通过循环,遍历所有订阅了 eventClass 事件的订阅者,并向每一个订阅者发送事件。 看它的发送事件的方法: postToSubscription(subscription, event, postingState.isMainThread);
噢,又回到了和之前 Subscribe 流程中处理粘滞事件相同的方法里————对声明不同线程模式的事件做不同的响应方法,最终都是通过invokeSubscriber()
反射订阅者类中的以onEvent
开头的方法。
我们继续来看EventBus
类,的最后一个入口方法unregister()
public synchronized void unregister(Object subscriber) {
List
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录