EventBus四种线程交付模式
原创 2016年11月05日 10:58:02
1、四种模式分别是:POSTING、MAIN、BACKGROUND、ASYNC。如果是想更新UI就使用MAIN模式,如果要进行耗时操作最好是使用ASYNC,因为这个模式能永远保证在不一样的线程中进行操作,而且都是子线程。
(1)POSTING:这种模式就是eventBus默认的模式,我们在使用的时候不需要再订阅者的方法的注解后面加任何东西(选择模式),但是这种只能在同一个线程中接收,也就是说,如果是在主线程中发布消息就只能在主线程中接收消息,如果是在子线程中,那么也只能在相同的子线程中去接收消息。如果非要声明POSTING的话,写法如下:
@Subscribe(threadMode = ThreadMode.POSTING)
public void
showMsgFromSecondActivity
(MessagePojo msg){ Log.
i
(
"test"
,
((String) msg.
obj
))
;
}
(2)MAIN:这种模式保证了订阅者指定的那个接收方法肯定要主线程中执行,可以放心的在里面执行更新UI操作。无论发布者是在主线程中还是在那一条子线程中发布消息,这边接收的都在主线程中。写法如下
@Subscribe(threadMode = ThreadMode.MAIN)
public void
showMsgFromSecondActivity
(MessagePojo msg){ Log.
i
(
"test"
,
((String) msg.
obj
))
;
}
(3)BACKGROUND:这种模式无论发布者是在主线程或者是那一条子线程中发布消息,接收的肯定是在子线程中,并且是这样理解:如果是在主线程中发布消息,那么就会随机开辟一条子线程来接收消息。如果是在子线程中发布消息,那么就会在相同的子线程来接收消息。写法如下:
@Subscribe(threadMode = ThreadMode.BACKGROUDN)
public void
showMsgFromSecondActivity
(MessagePojo msg){ Log.
i
(
"test"
,
((String) msg.
obj
))
;
}
(4)ASYNC:这种模式是无论你在那个线程中发布消息都会在不同的线程中接受消息。如果你在主线程中发布消息,就会随机的开辟一条子线程来接收消息;如果是在子线程中发布消息,就会开辟一条不同的子线程来接收消息。
写法如下:
@Subscribe(threadMode = ThreadMode.ASYNC)
public void
showMsgFromSecondActivity
(MessagePojo msg){ Log.
i
(
"test"
,
((String) msg.
obj
))
;
}
PostThread:直接在发布者线程调用事件处理方法
MainThread:如果发布者线程是主线程,那么直接在发布者线程(主线程)里边调用事件处理方法;如果发布者线程不是主线程,就把此事件送到主线程消息循环处理队列,在主线程
中处理此事件
BackgroundThread:如果发布者线程是主线程,那么把此事件发送到一个专门处理后台线程的消息循环处理队列,该队列管理多个后台线程;如果发布者不是主线程,那么在发布者线程中直接调用事件处理方法
Async:并不使用队列管理多个事件,也不管发布者处在主线程与否,为每一个事件单独开辟一个线程处理
- private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
- switch (subscription.subscriberMethod.threadMode) {
- case PostThread:
- /*在发布者的线程里边通过反射执行事件处理方法*/
- invokeSubscriber(subscription, event);
- break;
- case MainThread:
- /*如果发布者线程是主线程,直接在主线程里边通过反射执行事件处理方法*/
- if (isMainThread) {
- invokeSubscriber(subscription, event);
- /*如果发布者线程不是主线程,就把此事件加入主线程消息循环处理队列,在主线程中
- * 通过反射调用事件处理方法*/
- } else {
- mainThreadPoster.enqueue(subscription, event);
- }
- break;
- case BackgroundThread:
- /*如果发布者线程是主线程,那么就把此事件加入后台线程消息循环处理队列
- * 通过反射调用事件处理方法,此线程模式多个事件都在一个后台线程中循环处理
- * 通过队列管理多个事件*/
- 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);
- }
- }
MianThread线程模型参看上篇
Event源码解读详细注释(2)MainThread线程模型分析
BackgroundThread线程模型通过队列管理多个线程
- 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;
- /*进队列后判断此线程是否在执行,如果没有在执行就执行此线程(调用run方法)*/
- eventBus.getExecutorService().execute(this);
- }
- }
- }
- /*线程执行体*/
- @Override
- public void run() {
- try {
- try {
- /*循环处理消息*/
- while (true) {
- /*消息队列队首出队列,将被挂起1秒,直到有消息入队列或者1秒到时*/
- 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;
- }
- }
- }
Async线程模型为每一个事件单独开辟一个线程:
- 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);
- }
- }