1、获取单例实例:
public static EventBus getDefault() {
// 叨叨两句,双重锁机制 才是 单例创建的最佳姿势
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
2、调用 注册方法
public void register(Object subscriber) {
//获取订阅的当前类
Class<?> subscriberClass = subscriber.getClass();
//获取到当前订阅类中被@Subscribe 注解的方法
// 先会从缓存中获取,此处省略
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
// 订阅的时候会加入到
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
// 事件类型
Class<?> eventType = subscriberMethod.eventType;
// 创建新的订阅对象,用Subscription类包装订阅者以及订阅方法
Subscription newSubscription = new Subscription(subscriber,subscriberMethod);
// 取出所有订阅了该事件的Subscription集合
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
// 可能此eventType是第一次出现,初始化一下
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
// 优先级重新排序下
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
// 将新添加注解优先级高的添加到集合中
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 该订阅者所有的关心的事件类型集合 比如:一个Activity 有多个事件,就会有多个观察的实体Bean
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
// 第一次先初始化
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 如果当前订阅方法接受粘性事件,并且订阅方法关心的事件在粘性事件集合中,那么将该event事件post给subscriber
if (subscriberMethod.sticky) {
if (eventInheritance) {
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, 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 方法完成===========================
3、调用 post 方法:
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
// 构建了事件队列
List<Object> eventQueue = postingState.eventQueue;
// 每post 一个事件进来,就加入到事件队列中
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");
}
try {
// while 循环,按照 先进先出原则抽取事件分发
while (!eventQueue.isEmpty()) {
// 从 每次remove(0)可以看出每次都是从队列的头抽取对象
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
post 里面主要做了以下操作:
- 从ThreadLocal中获取PostingState,然后把事件Event添加到队列中 postingState.eventQueue
这里 PostingThreadState 类为:
/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
用来保存一些状态
- 判断当前时间是否发送,进到 if 中,设置是否是主线程以及 posting = true,然后循环调用队列 postingSingleEvent(eventQueue.remove(0), postingState),使用完的事件则被移除出队列
- 最后finally 设置属性为false
看下事件处理方法
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//该eventInheritance上面有提到,默认为true,即EventBus会考虑事件的继承树
//如果事件继承自父类,那么父类也会作为事件被发送
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);
}
// 结果判断,如果没找到订阅该事件的订阅者,发送 NoSubscriberEvent 事件
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
Inheritance:遗产,继承
看下调用的 postingSingleEventForEventType 这个方法
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// 1、根据事件类型eventType拿到方法集
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
//②保存当前状态到PostingState
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;
}
调用postToSubscription来执行事件
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
首先获取threadMode,即订阅方法运行的线程,如果是POSTING,那么直接调用invokeSubscriber()方法即可,如果是MAIN,则要判断当前线程是否是MAIN线程,如果是也是直接调用invokeSubscriber()方法,否则会交给mainThreadPoster来处理,其他情况相类似。这里会用到三个Poster,由于粘性事件也会用到这三个Poster,因此我把它放到下面来专门讲述。而EventBus#invokeSubscriber的实现也很简单,主要实现了利用反射的方式来调用订阅方法,这样就实现了事件发送给订阅者,订阅者调用订阅方法这一过程
invokeSubscriber
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
}
//...
}
整个流程图,更加清晰明了
流程图












网友评论