Guava中EventBus的使用和详解

来源:互联网 发布:linux less命令 退出 编辑:程序博客网 时间:2024/04/28 11:31

概述

        EventBus是Google Guava库中一个常用的组件。他使用了设计模式中的Observer(观察者)模式,实现了一个publish/subscribe模型的消息总线,简化了各组件之间之间的通信。

        Observer模式是比较常见和简单的设计模式之一,在JDK中,提供Observable和Observer这两个类可以快速使用。EventBus是Google在Guava中所实现的一个更加优雅和间的方案。更为重要的是,利用EventBus可以将事件发布者和事件订阅者解耦。发布者不再需要知道有那些订阅者,事件的派发由EventBus完成。


EventBus的基本用法:

        在传统的Android程序开发中,实现Observer模式往往会为被观察对象定义一个Listener接口,而观察者实现一个继承此接口的对象作为Listener并注册给被观察对象。而使用Guava中的EventBus后,如果想订阅消息,并不需要再去继承Observable所指定的接口。之需要在制定的方法中加上@Subscribe注解即可。

       观察者:
import com.google.common.eventbus.EventBus;public class TestObserver {private EventBus = new Event("TestEventBus");EventBus.register(this);private TestObservable mObservable;@Subscribepublic void onTestEvent(TestEvent event) {// implement event handling here}}

    被观察者:
public class TestObservable {private EventBus mEventBus;public void setEventBus(EventBus event_bus) {mEventBus = event_bus;}public void postSomeEvent() {if (mEventBus != null) {mEventBus.post(new TestEvent());}}}

    消息定义:
public class TestEvent{}

     可以看出,使用EventBus主要有以下步骤:
  1. 自定义一个消息类型
  2. 创建一个EventBus,并将观察者注册在这个EventBus中,并实现处理此消息类型的函数,以注解@Subscribe修饰。
  3. 被观察者获得EventBus对象,当需要发布消息的时候,向此EventBus对象发布Event。观察者便会对应的消息处理函数中收到此消息。

EventBus的代码分析

Register函数

        首先来分析EventBus类中的register函数:
  public void register(Object object) {    Multimap<Class<?>, EventSubscriber> methodsInListener =        finder.findAllSubscribers(object);    subscribersByTypeLock.writeLock().lock();    try {      subscribersByType.putAll(methodsInListener);    } finally {      subscribersByTypeLock.writeLock().unlock();    }  }
methodsInListener中会根据@Subscribe的注解查找所传入对象的EventHandler,并将事件类型与EventSubscriber的映射保留在subscribersByType对象中。
再来看AnnotatedSubscriberFinder中的findAllSubscribers方法:
  @Override  public Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object listener) {    Multimap<Class<?>, EventSubscriber> methodsInListener = HashMultimap.create();    Class<?> clazz = listener.getClass();    for (Method method : getAnnotatedMethods(clazz)) {      Class<?>[] parameterTypes = method.getParameterTypes();      Class<?> eventType = parameterTypes[0];      EventSubscriber subscriber = makeSubscriber(listener, method);      methodsInListener.put(eventType, subscriber);    }    return methodsInListener;  }
上面代码的内容就是通过反射读取Subscriber对象中带有@Subscribe注解的方法,并使用makeSubscriber将Subscriber对象和它的带@Subscribe对象的method对象封装成EventSubscriber标准事件处理对象:
  private static EventSubscriber makeSubscriber(Object listener, Method method) {    EventSubscriber wrapper;    if (methodIsDeclaredThreadSafe(method)) {      wrapper = new EventSubscriber(listener, method);    } else {      wrapper = new SynchronizedEventSubscriber(listener, method);    }    return wrapper;  }

Post函数:

  public void post(Object event) {    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());    boolean dispatched = false;    for (Class<?> eventType : dispatchTypes) {      subscribersByTypeLock.readLock().lock();      try {        Set<EventSubscriber> wrappers = subscribersByType.get(eventType);        if (!wrappers.isEmpty()) {          dispatched = true;          for (EventSubscriber wrapper : wrappers) {            enqueueEvent(event, wrapper);          }        }      } finally {        subscribersByTypeLock.readLock().unlock();      }    }    if (!dispatched && !(event instanceof DeadEvent)) {      post(new DeadEvent(this, event));    }    dispatchQueuedEvents();  }

首先获取事件类型,再将事件和对应的EventSubscriber加入队列:

  void enqueueEvent(Object event, EventSubscriber subscriber) {    eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber));  }
最后通过dispatchQueuedEvents()处理队列中的事件:
  void dispatchQueuedEvents() {    // don't dispatch if we're already dispatching, that would allow reentrancy    // and out-of-order events. Instead, leave the events to be dispatched    // after the in-progress dispatch is complete.    if (isDispatching.get()) {      return;    }    isDispatching.set(true);    try {      Queue<EventWithSubscriber> events = eventsToDispatch.get();      EventWithSubscriber eventWithSubscriber;      while ((eventWithSubscriber = events.poll()) != null) {        dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber);      }    } finally {      isDispatching.remove();      eventsToDispatch.remove();    }  }
dispatch的代码如下:

  void dispatch(Object event, EventSubscriber wrapper) {    try {      wrapper.handleEvent(event);    } catch (InvocationTargetException e) {      try {        subscriberExceptionHandler.handleException(            e.getCause(),            new SubscriberExceptionContext(                this,                event,                wrapper.getSubscriber(),                wrapper.getMethod()));      } catch (Throwable t) {        // If the exception handler throws, log it. There isn't much else to do!        Logger.getLogger(EventBus.class.getName()).log(Level.SEVERE,             String.format(            "Exception %s thrown while handling exception: %s", t,            e.getCause()),            t);      }    }  }
wrapper.hanleEvent()反射调用事件处理的方法:
  public void handleEvent(Object event) throws InvocationTargetException {    checkNotNull(event);    try {      method.invoke(target, new Object[] { event });    } catch (IllegalArgumentException e) {      throw new Error("Method rejected target/argument: " + event, e);    } catch (IllegalAccessException e) {      throw new Error("Method became inaccessible: " + event, e);    } catch (InvocationTargetException e) {      if (e.getCause() instanceof Error) {        throw (Error) e.getCause();      }      throw e;    }  }







0 0