Otto的使用和源码分析

来源:互联网 发布:吉他从零开始软件 编辑:程序博客网 时间:2024/05/01 12:37

Otto

Otto是square的一个event bus实现。

Event bus是一款针对Android优化的发布/订阅事件总线,主要功能是替代Intent、Handler、BroadCast
在Activity、Fragment、Service、Thread之间传递消息。其优点是开销小,代码更优雅,以及
将发送者和接收者解耦。

下载

在Android studio的module级别的build.gradle中dependencies下加入

compile 'com.squareup:otto:1.3.8'

使用

1.新建一个Bus实例,建议使用单例。

java
Bus bus = new Bus();

2.事件发布是非常重要的,因为它可以通知相应事件的订阅者某个动作已经发生。任何的类实例都可以
通过Bus发布事件,并且只有订阅了该事件的订阅者才会收到相应通知。

通过post方法发布一个新的事件

java
bus.post(new AnswerAvailableEvent(42));

除此之外,还有另外一种方法可以发布事件,这种形式会在Bus调用register方法时立即发布事件。
java
@Produce
public AnswerAvailableEvent produceAnswer() {
// Assuming 'lastAnswer' exists.
return new AnswerAvailableEvent(this.lastAnswer);
}

在方法级别上添加@Produce注解,方法的访问权限一定得是public的,并且其返回值类型是所发布
的事件类型。

这种事件发布形式还必需得在类实例中注册Bus实例
java
bus.register(this);

否则这个事件是无法让其订阅者接收到事件通知的。

3.订阅一个事件,你需要在方法级别上添加一个@Subscribe的注解。这个方法只能带有一个参数,
并且类型是你需要的订阅事件类型。

订阅一个事件,需要这样做

java
@Subscribe
public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}

需要注意的是,上面的方法其访问权限一定得是public的,其他无限制。

为了能够接收到事件,类实例需要注册Bus。通过下面方式注册
java
bus.register(this);

我们可以在适当的时候调用unregister方法取消Bus的注册
java
bus.unregister(this);

我们可以在Activity和Fragment的OnResume方法中注册Bus,然后在OnPause方法中取消注册。

4.默认的,新建的Bus是在主线程上活动的。
java
Bus bus1 = new Bus();
Bus bus2 = new Bus(ThreadEnforcer.MAIN);

上面两句代码是等价的。

你还可以实例化一个在任何线程都可以活动的Bus,
java
Bus bus3 = new Bus(ThreadEnforcer.ANY);

5.对于上面的使用方法,我是参照官方文档做一个大概的说明。大家可以使用git clone下官方提供
的sample研究具体的使用方法。

链接: https://github.com/square/otto

源码分析

Otto的源码只有九个类,阅读起来还是很容易理解的。

先看@Produce、@Subscribe这两个注解的定义。

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Produce {}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Subscribe {}

可以看出这两个注解都是在jvm运行时可获得的,并且都是作用在方法级别上。

再来看ThreadEnforcer、HandlerFinder两个接口。

public interface ThreadEnforcer {  /**   * 强制bus在某个确定的线程   */  void enforce(Bus bus);  /** A {@link ThreadEnforcer} that does no verification. */  ThreadEnforcer ANY = new ThreadEnforcer() {    @Override public void enforce(Bus bus) {      // Allow any thread.    }  };  /** A {@link ThreadEnforcer} that confines {@link Bus} methods to the main thread. */  ThreadEnforcer MAIN = new ThreadEnforcer() {    @Override public void enforce(Bus bus) {      if (Looper.myLooper() != Looper.getMainLooper()) {        throw new IllegalStateException("Event bus " + bus +        " accessed from non-main thread " + Looper.myLooper());      }    }  };}

ThreadEnforcer里面提供了两个默认的实现,其中我们新创建的Bus实例是默认使用Android的主线程的。

/** Finds producer and subscriber methods. */interface HandlerFinder {  Map<Class<?>, EventProducer> findAllProducers(Object listener);  Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener);  HandlerFinder ANNOTATED = new HandlerFinder() {    @Override    public Map<Class<?>, EventProducer> findAllProducers(Object listener) {      return AnnotatedHandlerFinder.findAllProducers(listener);    }    @Override    public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {      return AnnotatedHandlerFinder.findAllSubscribers(listener);    }  };}

HandlerFinder是用于查找使用了@Produce和@Subscribe的方法及事件类型的的。从方法定义就可以看出,一个
类中只能存在一个通过@Produce发布事件的方法,却可以存在多个使用@Subscribe的方法,即事件订阅者。

同样的,HandlerFinder里面也提供了一个默认的实现,委派AnnotatedHandlerFinder进行具体的操作。

其中,EventProducer的代码实现如下

class EventProducer {  /** Object sporting the producer method. */  final Object target;  /** Producer method. */  private final Method method;  EventProducer(Object target, Method method) {    if (target == null) {      throw new NullPointerException("EventProducer target cannot be null.");    }    if (method == null) {      throw new NullPointerException("EventProducer method cannot be null.");    }    this.target = target;    this.method = method;    /** 抑制java对修饰符访问权限的检查,提高jdk的反射效率 */    method.setAccessible(true);    ...  }  /**   * 通过反射调用方法   */  public Object produceEvent() throws InvocationTargetException {    if (!valid) {      throw new IllegalStateException(toString() + " has been invalidated and can no longer produce events.");    }    try {      return method.invoke(target);    } catch (IllegalAccessException e) {      throw new AssertionError(e);    } catch (InvocationTargetException e) {      if (e.getCause() instanceof Error) {        throw (Error) e.getCause();      }      throw e;    }  }  // 重写toString()、hashCode()、equals()方法}

EventHandler类的代码也差不多。

再来看看AnnotatedHandlerFinder到底干了哪些事。

final class AnnotatedHandlerFinder {  /*   * 用于保存使用了@Produce注解的类及方法,其中map的键是监听类,值是一个map,值的map的   * 键是事件类型,值是方法   */  private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =    new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();  /** 用于保存使用了@Subscribe注解的类及方法 */  private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =    new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();  /** 加载使用了@Produce注解的类及方法 */  private static void loadAnnotatedProducerMethods(Class<?> listenerClass,      Map<Class<?>, Method> producerMethods) {    Map<Class<?>, Set<Method>> subscriberMethods = new HashMap<Class<?>, Set<Method>>();    loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);  }  /** 加载使用了@Subscribe注解的类及方法 */  private static void loadAnnotatedSubscriberMethods(Class<?> listenerClass,      Map<Class<?>, Set<Method>> subscriberMethods) {    Map<Class<?>, Method> producerMethods = new HashMap<Class<?>, Method>();    loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);  }  /**   * 加载所有使用了@Produce和@Subscribe注解的方法   */  private static void loadAnnotatedMethods(Class<?> listenerClass,      Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) {    for (Method method : listenerClass.getDeclaredMethods()) {      // The compiler sometimes creates synthetic bridge methods as part of the      // type erasure process. As of JDK8 these methods now include the same      // annotations as the original declarations. They should be ignored for      // subscribe/produce.      if (method.isBridge()) {        continue;      }      if (method.isAnnotationPresent(Subscribe.class)) {        Class<?>[] parameterTypes = method.getParameterTypes();        /** 参数个数判断 */        if (parameterTypes.length != 1) {          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "              + parameterTypes.length + " arguments.  Methods must require a single argument.");        }        Class<?> eventType = parameterTypes[0];        /** 判断是否为接口 */        if (eventType.isInterface()) {          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType              + " which is an interface.  Subscription must be on a concrete class type.");        }        /** 判断方法的访问权限是否为public */        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {          throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType              + " but is not 'public'.");        }        Set<Method> methods = subscriberMethods.get(eventType);        if (methods == null) {          methods = new HashSet<Method>();          subscriberMethods.put(eventType, methods);        }        methods.add(method);      } else if (method.isAnnotationPresent(Produce.class)) {        Class<?>[] parameterTypes = method.getParameterTypes();        /** 参数个数判断 */        if (parameterTypes.length != 0) {          throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "              + parameterTypes.length + " arguments.  Methods must require zero arguments.");        }        /** 方法返回类型是否为Void.class判断 */        if (method.getReturnType() == Void.class) {          throw new IllegalArgumentException("Method " + method              + " has a return type of void.  Must declare a non-void type.");        }        Class<?> eventType = method.getReturnType();        /** 是否为接口判断 */        if (eventType.isInterface()) {          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType              + " which is an interface.  Producers must return a concrete class type.");        }        /** 方法返回值判断 */        if (eventType.equals(Void.TYPE)) {          throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");        }        /** 判断方法的访问权限是否为public */        if ((method.getModifiers() & Modifier.PUBLIC) == 0) {          throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType              + " but is not 'public'.");        }        /** 判断此类事件是否已经由@Produce发布过 */        if (producerMethods.containsKey(eventType)) {          throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");        }        producerMethods.put(eventType, method);      }    }    /** 把查找到的分别放进缓存 */    PRODUCERS_CACHE.put(listenerClass, producerMethods);    SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);  }  /** 查找所有的@Produce */  static Map<Class<?>, EventProducer> findAllProducers(Object listener) {    final Class<?> listenerClass = listener.getClass();    Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>();    Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass);    /** 如果缓存中不存在 */    if (null == methods) {      methods = new HashMap<Class<?>, Method>();      loadAnnotatedProducerMethods(listenerClass, methods);    }    if (!methods.isEmpty()) {      for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {        /** 包装到EventProducer */        EventProducer producer = new EventProducer(listener, e.getValue());        handlersInMethod.put(e.getKey(), producer);      }    }    return handlersInMethod;  }  /** 查找所有的@Subscribe */  static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {    ...  }  private AnnotatedHandlerFinder() {    // No instances.  }}

阅读AnnotatedHandlerFinder之后,可以很清楚地知道它主要是负责查找指定类中带有@Produce
和@Subscribe注解的方法,并且把相应的事件类型放到相应的缓存中。

其中HandlerFinder的默认实现ANNOTATED就是使用了AnnotatedHandlerFinder.findAllProducers(listener)
和AnnotatedHandlerFinder.findAllSubscribers(listener)来完成具体的注解查找工作的。

最后只剩下最重要的Bus类了。

因为我们使用Otto是从在Activity或Fragment的OnResume方法中进行register()开始的,所有我们
看看register()到底干了什么事。

public void register(Object object) {  if (object == null) {    throw new NullPointerException("Object to register must not be null.");  }  /** 确认所在线程 */  enforcer.enforce(this);  /** 查找所有的@Produce */  Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);  for (Class<?> type : foundProducers.keySet()) {    /** 判断是否当前类已经存在一个使用@Produce的方法 */    final EventProducer producer = foundProducers.get(type);    EventProducer previousProducer = producersByType.putIfAbsent(type, producer);    //checking if the previous producer existed    if (previousProducer != null) {      throw new IllegalArgumentException("Producer method for type " + type        + " found on type " + producer.target.getClass()        + ", but already registered by type " + previousProducer.target.getClass() + ".");    }    Set<EventHandler> handlers = handlersByType.get(type);    if (handlers != null && !handlers.isEmpty()) {      for (EventHandler handler : handlers) {        /** 分发事件 */        dispatchProducerResultToHandler(handler, producer);      }    }  }  /** 查找所有的@Subscribe */  Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object);  for (Class<?> type : foundHandlersMap.keySet()) {    Set<EventHandler> handlers = handlersByType.get(type);    if (handlers == null) {      //concurrent put if absent      Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>();      handlers = handlersByType.putIfAbsent(type, handlersCreation);      if (handlers == null) {          handlers = handlersCreation;      }    }    final Set<EventHandler> foundHandlers = foundHandlersMap.get(type);    if (!handlers.addAll(foundHandlers)) {      throw new IllegalArgumentException("Object already registered.");    }  }  for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) {    Class<?> type = entry.getKey();    EventProducer producer = producersByType.get(type);    if (producer != null && producer.isValid()) {      Set<EventHandler> foundHandlers = entry.getValue();      for (EventHandler foundHandler : foundHandlers) {        if (!producer.isValid()) {          break;        }        if (foundHandler.isValid()) {          /** 分发事件 */          dispatchProducerResultToHandler(foundHandler, producer);        }      }    }  }}

到了这里,我们已经很清楚了,register方法主要是查找所有的@Produce和@Subscribe并且进行事件
分发给handler处理。

private void dispatchProducerResultToHandler(EventHandler handler, EventProducer producer) {  Object event = null;  try {    /** 通过反射调用方法,前面已经在EventProducer分析过,发布@Produce的事件 */    event = producer.produceEvent();  } catch (InvocationTargetException e) {    throwRuntimeException("Producer " + producer + " threw an exception.", e);  }  if (event == null) {    return;  }  /** 再次分发事件 */  dispatch(event, handler);}protected void dispatch(Object event, EventHandler wrapper) {  try {    /** 通过反射调用方法,前面已经在EventHandler分析过,这里就是接收到事件通知之后执行具体的操作,执行@Subscribe的方法 */    wrapper.handleEvent(event);  } catch (InvocationTargetException e) {    throwRuntimeException(        "Could not dispatch event: " + event.getClass() + " to handler " + wrapper, e);  }}

至于unregister和register方法则是相反的操作,移除当前类及方法的监听。

当我们调用post发布事件又发生了什么事呢?

下面我们来看看post方法的实现。

public void post(Object event) {  if (event == null) {    throw new NullPointerException("Event to post must not be null.");  }  enforcer.enforce(this);  Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());  boolean dispatched = false;  for (Class<?> eventType : dispatchTypes) {    Set<EventHandler> wrappers = getHandlersForEventType(eventType);    if (wrappers != null && !wrappers.isEmpty()) {      dispatched = true;      for (EventHandler wrapper : wrappers) {        /** 把事件添加进队列 */        enqueueEvent(event, wrapper);      }    }  }  /** 没有订阅者的事件没有被分发,被封装成DeadEvent再次post出去 */  if (!dispatched && !(event instanceof DeadEvent)) {    post(new DeadEvent(this, event));  }  /** 逐一分发事件队列的事件方法 */  dispatchQueuedEvents();}protected void enqueueEvent(Object event, EventHandler handler) {  eventsToDispatch.get().offer(new EventWithHandler(event, handler));}protected 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 {    while (true) {      EventWithHandler eventWithHandler = eventsToDispatch.get().poll();      if (eventWithHandler == null) {        break;      }      if (eventWithHandler.handler.isValid()) {        /** 上面这个方法已经列出分析过 */        dispatch(eventWithHandler.event, eventWithHandler.handler);      }    }  } finally {    isDispatching.set(false);  }}

最后,整个Otto的源码分析过程就完成了。

0 0
原创粉丝点击