上一节在阅读了EventBus的消息发送后,停在了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); } }
在不同的模式下,当前方法在不同线程中调用,会使用不同的Poster。上次对这一点没有深究,今天来粗略的看一看。
从上面的代码中,我们可以看到,除了直接执行方法 invokeSubscriber(subscription, event);外,还有几个特殊的Poster,分别是mainThreadPoster,backgroundPoster,和asyncPoster。
我们来一一阅读。
mainThreadPoster的类叫作HandlerPoster,代码不长,总共80来行。
final class HandlerPoster extends Handler { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; private final EventBus eventBus; private boolean handlerActive; HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { super(looper); this.eventBus = eventBus; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); } void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { queue.enqueue(pendingPost); if (!handlerActive) { handlerActive = true; if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } } } } @Override public void handleMessage(Message msg) { boolean rescheduled = false; try { long started = SystemClock.uptimeMillis(); while (true) { 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; if (timeInMethod >= maxMillisInsideHandleMessage) { if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } rescheduled = true; return; } } } finally { handlerActive = rescheduled; } } }
可以看到HandlerPoster继承了Handler。方法enqueue主要做了两件事。
一、将事件请求放入请求队列queue中。
二、发送一个message到MainLooper中。
每当HandlerPoster发送message,其中的handleMessage就要开始工作。EventBus为其设置了最大工作时间。在工作时间内,程序会不断地从queue中poll出请求,在主线程中执行它,直到queue队列为空,或是到达最大工作时间,才会结束。我们可以看到,HandlerPoster其实就是对消息的发送做了处理,通过Handler,将其置于MainThread中来执行。
BackgroundPoster:
BackgroundPoster则是实现了Runnable接口。
final class BackgroundPoster implements Runnable { private final PendingPostQueue queue; private final EventBus eventBus; private volatile boolean executorRunning; BackgroundPoster(EventBus eventBus) { this.eventBus = eventBus; queue = new PendingPostQueue(); } public void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { queue.enqueue(pendingPost); if (!executorRunning) { executorRunning = true; eventBus.getExecutorService().execute(this); } } } @Override public void run() { try { try { while (true) { PendingPost pendingPost = queue.poll(1000); if (pendingPost == null) { synchronized (this) { // Check again, this time in synchronized pendingPost = queue.poll(); if (pendingPost == null) { executorRunning = false; return; } } } eventBus.invokeSubscriber(pendingPost); } } catch (InterruptedException e) { Log.w("Event", Thread.currentThread().getName() + " was interruppted", e); } } finally { executorRunning = false; } } }
BackgroundPoster也维护了一个请求队列。与HandlerPoster不同的是,它不再使用message来发动任务的执行。而是eventBus.getExecutorService().execute(this);这个方法最终可以追溯到EventBusBuilder中的DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();也就是说,在BackgroundPoster中执行的任务一定不在主线程。另一个与HandlerPoster不同的点是,BackgroundPoster没有最大工作时间,但它有个最大等待时间——1000ms。如果队列为空,在等待1000ms后,队列中依然没有新的事件加入,再表示事件请求已全部执行。
AsyncPoster:
AsyncPoster的实现最为简单,它的功能是,不能当前处于什么线程,一定都会新开一个线程来执行这个任务。
class AsyncPoster implements Runnable { private final PendingPostQueue queue; private final EventBus eventBus; AsyncPoster(EventBus eventBus) { this.eventBus = eventBus; queue = new PendingPostQueue(); } public void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); queue.enqueue(pendingPost); eventBus.getExecutorService().execute(this); } @Override public void run() { PendingPost pendingPost = queue.poll(); if(pendingPost == null) { throw new IllegalStateException("No pending post available"); } eventBus.invokeSubscriber(pendingPost); } }
代码比较简单,我们可以看出AsyncPoster是在BackgroundPoster上做的减法。去掉了线程保护(因为新开),去掉了wait(也是因为新开)。
通过以上阅读,我们大致对EventBus的事件发送机制有了了解。下一节,我们将开始阅读,它的订阅机制。
Done~