相关文章
Android事件总线(一)EventBus3.0用法全解析
Android事件总线(二)EventBus3.0源码解析
Android事件总线(三)otto用法全解析

前言

上一篇文章中讲到了otto的用法,这一篇我们来讲一下otto的源码。可能有人觉得otto过时了,但是通过源码我们学习的是高手设计otto时的设计理念,这种设计理念是不过时的。

otto各个类的作用

首先先来看一下otto的源码的各个类的作用,如下图所示。

如图所示,otto的源码并不多,主要的类的功能如下:
- Produce、Subscribe:发布者和订阅者注解类。
- Bus:事件总线类,用来注册和取消注册,维护发布-订阅模型,并处理事件调度分发。
- HandlerFinder、AnnotatedHandlerFinder:用来查找发布者和订阅者。
- EventProducer、EventHandler:分别封装发布者和订阅者的数据结构。

otto构造函数

在使用otto时,首先要创建Bus类,Bus类的构造函数如下所示。

public Bus() {    this(DEFAULT_IDENTIFIER);  }

这个DEFAULT_IDENTIFIER是一个字符串”default”,this调用了Bus类的另一个构造函数:

 public Bus(String identifier) {    this(ThreadEnforcer.MAIN, identifier);  }

ThreadEnforcer.MAIN意味着默认在主线程中调度事件,再往里看this又调用了什么,如下所示。

  public Bus(ThreadEnforcer enforcer, String identifier) {    this(enforcer, identifier, HandlerFinder.ANNOTATED);  }

第一个参数我们提到了,就是事件调度的简称,identifier为Bus的名称,默认为”default”。而identifier则是HandlerFinder,用于在register、unregister的时候寻找所有的subscriber和producer。再往里查看this又调用了什么,如下所示。

  Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {    this.enforcer =  enforcer;    this.identifier = identifier;    this.handlerFinder = handlerFinder;  }

这个是最终调用的Bus的构造函数,在这里要首先记住handlerFinder 指的就是传进来的HandlerFinder.ANNOTATED,后面在注册时会用到handlerFinder这个属性。

注册

生成bus类后,我们要调用它的register方法来进行注册。register方法如下所示。

public void register(Object object) {    if (object == null) {      throw new NullPointerException("Object to register must not be null.");    }    enforcer.enforce(this);    Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);//1...}

注释1出调用了handlerFinder的findAllProducers方法,此前讲到构造函数时,我们知道这个handlerFinder指的是HandlerFinder.ANNOTATED,ANNOTATED的代码如下所示。

 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);    }  };

从上面的代码的findAllProducers方法和findAllSubscribers方法的返回值可以推断出一个注册类只能有一个发布者,却可以有多个订阅者。findAllProducers方法最终调用的是AnnotatedHandlerFinder的findAllProducers方法:

  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);//1    if (null == methods) {      methods = new HashMap<Class<?>, Method>();      loadAnnotatedProducerMethods(listenerClass, methods);//2    }    if (!methods.isEmpty()) {      for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {//3        EventProducer producer = new EventProducer(listener, e.getValue());        handlersInMethod.put(e.getKey(), producer);      }    }    return handlersInMethod;  }

PRODUCERS_CACHE是一个ConcurrentHashMap,它的key为bus.register()时传入的class,而value是一个map,这个map的key是事件的class,value是生产事件的方法。注释1处首先在PRODUCERS_CACHE根据传入的对象的类型查找是否有缓存的事件方法,如果没有就调用注释2处的代码利用反射去寻找所有使用了@Produce注解的方法,并且将结果缓存到PRODUCERS_CACHE中。接着在注释3处遍历这些事件方法,并为每个事件方法创建了EventProducer类,并将这些EventProducer类作为value存入handlersInMethod并返回。接下来我们返回register方法。如下所示。

  public void register(Object object) {    if (object == null) {      throw new NullPointerException("Object to register must not be null.");    }    enforcer.enforce(this);    Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);    for (Class<?> type : foundProducers.keySet()) {      final EventProducer producer = foundProducers.get(type);      EventProducer previousProducer = producersByType.putIfAbsent(type, producer);//1      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);//2        }      }    }    ...  }

调用完findAllProducers方法后,会在注释1处检查是否有该类型的发布者已经存在,如果存在则抛出异常,不存在则调用注释2处的dispatchProducerResultToHandler方法来触发和发布者对应的订阅者来处理事件。接下来register方法的后一部分代码就不帖上来了,跟此前的流程大致一样就是调用findAllSubscribers方法来查找所有使用了@Subscribe注解的方法,跟此前不同的是一个注册类可以有多个订阅者,接下来判断是否有该类型的订阅者存在,也就是判断注册类是否已经注册,如果存在则抛出异常,不存在则查找是否有和这些订阅者对应的发布者,如果有的话,就会触发对应的订阅者处理事件。

发送事件

我们会调用Bus的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());//1    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);//2        }      }    }    if (!dispatched && !(event instanceof DeadEvent)) {      post(new DeadEvent(this, event));    }    dispatchQueuedEvents();//3  }

注释1处的flattenHierarchy方法首先会从缓存中查找传进来的event(消息事件类)的所有父类,如果没有则找到event的所有父类并存储入缓存中。接下来遍历这些父类找到它们的所有订阅者,并在注释2处将这些订阅者压入线程的事件队列中。并在注释3处调用dispatchQueuedEvents方法依次取出事件队列中的订阅者来处理相应event的事件。

取消注册

取消注册时,我们会调用Bus的unregister方法,unregister方法如下所示。

  public void unregister(Object object) {    if (object == null) {      throw new NullPointerException("Object to unregister must not be null.");    }    enforcer.enforce(this);    Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);//1    for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {      final Class<?> key = entry.getKey();      EventProducer producer = getProducerForEventType(key);      EventProducer value = entry.getValue();      if (value == null || !value.equals(producer)) {        throw new IllegalArgumentException(            "Missing event producer for an annotated method. Is " + object.getClass()                + " registered?");      }      producersByType.remove(key).invalidate();//2    }  ...  }

取消注册分为两部分,一部分是订阅者取消注册,另一部分是发布者取消注册。这两部分的代码类似,因此,上面的代码只列出了发布者取消注册的代码。在注释1处得到所有使用@Produce注解的方法,并遍历这些方法,调用注释2处的代码从缓存中清除所有和传进来的注册类相关的发布者,来完成发布者的取消注册操作。

欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关技术干货。
扫一扫下方二维码即可关注:

更多相关文章

  1. Android 应用程序查找设备的方法——以串口为例
  2. android中使用httpclient方法获得网页内容并对json对象解析
  3. 【Android】Android事件分发机制的学习笔记和理解
  4. Android Studio3.0开发JNI流程------在Android原程序添加自己类
  5. 利用Android的Matrix类实现J2ME的drawRegion的镜像方法
  6. 调用Android自带日历功能(日历列表单、添加一个日历事件)

随机推荐

  1. android java 层参数重载glVertexAttribP
  2. Unable to start activity ComponentInfo
  3. Android(安卓)system.img 打包解包
  4. mediaplayer实现音乐播放
  5. Android(安卓)studio 原生自带下拉加载控
  6. Android下查询系统源码看短信的显示
  7. Android中 Webview中js与Activity的交互
  8. Xamarin Mono For Android(安卓)4.12 安
  9. Android(安卓)单元测试: 首先,从是什么开
  10. Genimotion 解决 INSTALL_FAILED_CPU_ABI