这一篇我们来分析一下post()及postSticky()相关的源码,在进入post()方法之前,我们先来了解一个数据结构PostingThreadState,它也是EventBus的一个静态内部类:
EventBus.java
final static class PostingThreadState {
//存放Event对象的列表
final List<Object> eventQueue = new ArrayList<>();
//是否正在处理Event事件
boolean isPosting;
//是否是主线程
boolean isMainThread;
//一个数据结构绑定了订阅者对象(如:MainActivity对象)和订阅方法
Subscription subscription;
//Event 事件
Object event;
//是否已取消
boolean canceled;
}
并且在EventBus中这个类是和ThreadLocal一起使用的,也就是说在使用中它是线程私有的。
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
//重写了ThreadLocal的initialValue(),默认返回一个PostingThreadState对象,而不是null
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
接下来打开post()方法:
EventBus.java
public void post(Object event) {
//得到线程私有的postingState对象
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
//将传入的event对象放入list列表
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 {
//循环处理list中的event事件
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
//恢复初始值
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
继续跟入方法postSingleEvent():
EventBus.java
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
//得到event事件的类型,如:String.class
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) { //默认为true
//这里获取了eventClass及其向上的所有父类类型及实现的接口类型,比较简单就不做展开了
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));
}
}
}
继续跟入postSingleEventForEventType()方法:
EventBus.java
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//subscriptionsByEventType是在register()中填充的数据,这里根据eventClass作为key,取到了所有Event事件为eventClass类型的订阅方法和订阅者对象(即Subscription)
subscriptions = subscriptionsByEventType.get(eventClass);
}
// 列表不为空的话,遍历列表
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted;
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():
EventBus.java
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//根据订阅方法的不同threadMode进行处理
switch (subscription.subscriberMethod.threadMode) {
//在哪个线程执行的post方法,就在哪个线程执行调订阅方法
case POSTING:
invokeSubscriber(subscription, event);
break;
//在android主线程执行调订阅方法
case MAIN:
//当前线程为主线程
if (isMainThread) {
//直接执行(阻塞)
invokeSubscriber(subscription, event);
} else {
//注释2@postToSubscription 进入队列,排队执行(非阻塞),使用了handler机制
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
// 与MAIN逻辑相反,优先进入队列,排队执行(非阻塞)
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber //直接执行(阻塞)
invokeSubscriber(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);
}
}
无论走到哪个分支,最后都会调用:
void invokeSubscriber(Subscription subscription, Object event) {
try {
//通过反射invoke()的方式去执行订阅方法
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
那我们再回过头来看如果post线程不是主线程,而订阅方法又需要在主线程执行又是怎么实现的呢,如注释2@postToSubscription处的情况。
跟踪代码可知mainThreadPoster对象是HandlerPoster类型:
EventBus.java
EventBus(EventBusBuilder builder) {
......
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
......
}
DefaultAndroidMainThreadSupport.java
public class DefaultAndroidMainThreadSupport implements MainThreadSupport {
@Override
public boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
//传入的是Main主线程的Looper对象
return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);
}
}
我们来看HandlerPoster.java这个类:
//HandlerPoster继承了Handler,所有它有了跨线程通讯的能力,Poster接口比较简单只定义了一个enqueue()方法
public class HandlerPoster extends Handler implements Poster {
//存放PendingPost的队列
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
// 是否MessageQueue中已有我们发送的消息正在排队等待执行
private boolean handlerActive;
public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
//传入的looper为主线程的looper,所以下面sendMessage()发送消息是发送到主线程looper中的MessageQueue中,因而handleMessage()处理message是在主线程中进行的。
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
//将传入的subscription和event对象封装成一个PendingPost对象,
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//添加到队列
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
// 发送空message消息,返回true,说明message成功添加到messageQueue
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
// 开始处理messageQueue中的消息
boolean rescheduled = false;
try {
//记录一个开始处理的时间
long started = SystemClock.uptimeMillis();
//循环处理PendingPostQueue中的任务
while (true) {
//取出队列中的头个pendingPost对象
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
// 同步块检查
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
//在主线程中执行订阅方法
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
// 超时检查,以免PendingPostQueue中任务过多阻塞主线程
if (timeInMethod >= maxMillisInsideHandleMessage) {
//超时的话重新发送消息,进入MessageQueue等待执行
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
// 退出while循环
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
而BackgroundPoster和AsyncPoster的逻辑也是大同小异区别在于在线程池线程中去执行订阅方法,这里就不再详细介绍。post()方法源码基本梳理完成,再看postSticky()方法就非常简单了,因为postSticky()调用了post()方法:
EventBus.java
public void postSticky(Object event) {
//同步锁
synchronized (stickyEvents) {
//细心的同学会发现这个stickyEvents曾经出现过,在register()方法中,回过头去看一眼吧
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
到此,发送Event事件的源码我们分析完毕。