EventBus是一個事件(消息)發佈訂閱框架,使用了觀察者模式,可以同步也可以異步。選擇同步還是異步就根據個人場景來進行選擇。
AsyncEventBus就是異步的,是在EventBus的基礎上,加入了Executor來異步執行訂閱者處理事件的方法,這樣就不會因爲訂閱事件執行過慢而阻塞主線程,源碼如下:
@Beta
public class AsyncEventBus extends EventBus {
public AsyncEventBus(String identifier, Executor executor) {
super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
}
public AsyncEventBus(Executor executor) {
super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
}
先通過代碼看一下它簡單的用法:
事件處理器1:
public class EventApple {
@Subscribe
public void eat(String apple){
System.out.println("吃"+apple);
}
}
事件處理器2:
public class EventRun {
@Subscribe
public void run(Integer run){
System.out.println("跑步第"+run+"名");
}
}
註冊事件處理器,發佈事件。
public class TestEventBus {
public static void main (String[] args){
EventBus eventBus=new EventBus();
eventBus.register(new EventApple());
eventBus.register(new EventRun());
eventBus.post(5);
eventBus.post("蘋果");
}
}
輸出:
跑步第5名
吃蘋果
EventBus的基本用法就是:
1、創建EventBus對象,EventBus的構造函數,源碼如下:
public EventBus() {
this("default");
}
public EventBus(String identifier) {
this(identifier, MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), EventBus.LoggingHandler.INSTANCE);
}
public EventBus(SubscriberExceptionHandler exceptionHandler) {
this("default", MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);
}
EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) {
this.subscribers = new SubscriberRegistry(this);
this.identifier = (String)Preconditions.checkNotNull(identifier);
this.executor = (Executor)Preconditions.checkNotNull(executor);
this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher);
this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler);
}
構造函數有三個:
第一個是:創建一個新的EventBus對象,默認名稱爲default
第二個是:使用指定的標識符創建一個新的EventBus
第三個shi :使用SubscriberExceptionHandler ,處理subscribers處理事件時拋出異常。
2、註冊事件處理器,源碼:
void register(Object listener) {
Multimap<Class<?>, Subscriber> listenerMethods = this.findAllSubscribers(listener);
Collection eventMethodsInListener;
CopyOnWriteArraySet eventSubscribers;
for(Iterator var3 = listenerMethods.asMap().entrySet().iterator(); var3.hasNext(); eventSubscribers.addAll(eventMethodsInListener)) {
Entry<Class<?>, Collection<Subscriber>> entry = (Entry)var3.next();
Class<?> eventType = (Class)entry.getKey();
eventMethodsInListener = (Collection)entry.getValue();
eventSubscribers = (CopyOnWriteArraySet)this.subscribers.get(eventType);
if (eventSubscribers == null) {
CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet();
eventSubscribers = (CopyOnWriteArraySet)MoreObjects.firstNonNull(this.subscribers.putIfAbsent(eventType, newSet), newSet);
}
}
}
事件處理器中要被執行的事件,都需要使用@Subscribe註解,表示是註冊的事件。3、發佈事件
public void post(Object event) {
Iterator<Subscriber> eventSubscribers = this.subscribers.getSubscribers(event);
if (eventSubscribers.hasNext()) {
this.dispatcher.dispatch(event, eventSubscribers);
} else if (!(event instanceof DeadEvent)) {
this.post(new DeadEvent(this, event));
}
}
發佈事件之後,就去註冊的事件處理器中查找有@Subscribe的註解的方法,找到對應參數類型的事件就執行。
如果在註冊的處理器中沒有找到發佈的事件,那麼EventBus就會把該事件包裝成個DeadEvent事件來重新發布,我們可以提供下面的事件處理來處理DeadEvent:
@Subscribe
public void onEvent(DeadEvent de) {
System.out.println("發佈了錯誤的事件:" + de.getEvent());
}
AsyncEventBus是異步的,只需要在AsyncEventBus的構造函數中添加Executor即可:
AsyncEventBus asyncEventBus=new AsyncEventBus(Executors.newFixedThreadPool(10));
其他操作和原始的EventBus是一樣的。
EventBus中默認的訂閱方式是線程不安全的,但是在異步調度的時候會自動將其包裝成線程安全的。對於一般的線程安全的實現上可以通過@AllowConcurrentEvents註解來標示。