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注解来标示。