EventBus

286 阅读2分钟

EventBus是Android事件发布/订阅框架。

Handler的2种通信

  1. 主线程发送消息sendMessage(msg),子线程处理消息handleMessage(msg)
  2. 子线程发送消息sendMessage(msg),主线程处理消息handleMessage(msg)

EventBus流程

EventBus使用

  1. 导入依赖
  2. 定义一个事件Event
  3. @Subscribe标注订阅者,threadMode = ThreadMode.MAIN 表示onMessageEvent方法在主线程中运行
  4. onStartonStop中注册、解注册事件。注册、解注册尽量和组件(Activity/Fragment)的生命周期绑定
  5. 发送事件,调用EventBus.getDefault().post传入自定义的事件
  • 发送事件后,所有注册该事件的订阅者都能接收到该事件(msg="Hello everyone!")。

EventBus实现原理

  • EventBus.getDefault()用来创建EventBus实例
    • 单例,并使用双重锁校验
    • 注意构造函数是public的,一般单例模式下构造函数时private的
      • 跟进DEFAULT_BUILDER,发现使用的是Build内部类构建者模式进行对象创建
      • EventBus用到ThreadLocal,ThreadLocal可以在指定的线程中存储/获取数据,其他线程无法获取
      • 2个HashMap
        subscriptionsByEventType: key -event; value -subscriber。当发送事件时,可以由该HashMap根据event找到订阅者。
        typesBySubscriber: key -subscriber; value -event。用于注册/解注册事件。
      • 3个Poster
      1. HandlerPoster: extend Handler。不停地从队列中获取PendingPost,通过eventBus.invokeSubscriber(pendingPost)分发PendingPost。
      2. BackgroundPoster: extend Runnable。不断从队列中取数据,eventBus.invokeSubscriber(pendingPost)分发,直到取完为止
      3. AsyncPoster: extend Runnable。从队列中获取一个PendingPost,eventBus.invokeSubscriber(pendingPost)分发。

粘性事件

findUsingReflectionInSingle方法流程

  1. 利用反射查找订阅者订阅的方法
  2. 遍历所有方法
    getModifiers()拿到方法的修饰符,getParameterTypes()拿到方法的参数。由于EventBus只允许订阅方法的订阅事件是一个,则根据一个参数的判断(length == 1)过滤出订阅方法。
    getAnnotation(Subscribe.class)过滤出只被@Subscribe修饰过的方法methodName1。
    methodName1.threadMode()获取被@Subscribe修饰过的方法的线程模式。

subscribe方法流程

  • subscriptionsByEventType是一个HashMap,可以通过它找到订阅者、订阅方法、参数等。
  • typesBySubscriber是一个HashMap,可找到该订阅者订阅的所有事件。
  • checkPostStickyEventToSubscription中会先判断是否是粘性事件,是否考虑继承关系,最后分发事件。

post方法流程

  • 通过保存状态的HashMap(subscriptionsByEventType)找到subscription的集合,然后依次遍历,通过postToSubscription方法完成订阅。
    -- 进入postToSubscription
    • 4个case的判断,不同的case使用不同的Poster(见上)分发。