EventBus 源码分析(下篇)
2018-09-30 本文已影响9人
糖葫芦_倩倩
上篇 EventBus 源码分析(上篇) 说到注册订阅的前半部分,此篇用来分析发送事件到接收事件这个过程。
1. 发送事件
示例:
EventBus.getDefault().post(new RemindBean("2018-02-12","happy"));
post
:
/** Posts the given event to the event bus. */
public void post(Object event) {
- 1.获取当前线程的postingThreadState 对象
PostingThreadState postingState = currentPostingThreadState.get();
- 2. 获取里面那个事件队列
List<Object> eventQueue = postingState.eventQueue;
- 3. 将事件添加到队列中去
eventQueue.add(event);
- 4. 判断当前的event 是否在 posting
if (!postingState.isPosting) {
- 5. 是否是主线程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
- 6. 判断是否取消
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {//不为空,进入循环
- 7.按照顺序,post一个 remove一个
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
PostingThreadState
大概看一眼
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
再就是 postSingleEvent(eventQueue.remove(0), postingState);
方法:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
- 1. 获取event的字节码(例如就是:RemindBean.class)
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {//默认为true
- 2. 根据eventClass 的字节码查找
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
- 3.循环遍历
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
- 4.根据事件,字节码查找订阅者
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
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));
}
}
}
postSingleEventForEventType
:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
- 1.根据字节码取出subscriptions,还记得我们之前在subscribe这个方法的时候,
把subscrber,subscriberMethod 封装成一个subscription 对象。
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
- 2. 取出每一个subscription 对象
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
- 3. post到相应的线程中回调
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://一般没定义的,这个就是post在哪个线程,响应就在哪个线程执行
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);
}
}
invokeSubscriber
:
void invokeSubscriber(Subscription subscription, Object event) {
try {
- 反射拿到字节码clazz 反射调用方法,就收到消息了
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
end.