EventBus源码分析

EventBus创建

getDefault()

getDefault()中使用了双重校验并加锁的单例模式来创建EventBus实例。

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
  EventBus instance = defaultInstance;
  if (instance == null) {
    synchronized (EventBus.class) {
      instance = EventBus.defaultInstance;
      if (instance == null) {
        instance = EventBus.defaultInstance = new EventBus();
      }
    }
  }
  return instance;
}

创建EventBus,传入了一个默认的EventBusBuilder

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
  this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
  logger = builder.getLogger();
  subscriptionsByEventType = new HashMap<>();
  typesBySubscriber = new HashMap<>();
  stickyEvents = new ConcurrentHashMap<>();
  mainThreadSupport = builder.getMainThreadSupport();
  //创建Poster
  mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
  backgroundPoster = new BackgroundPoster(this);
  asyncPoster = new AsyncPoster(this);
  indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
  subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
          builder.strictMethodVerification, builder.ignoreGeneratedIndex);
  logSubscriberExceptions = builder.logSubscriberExceptions;
  logNoSubscriberMessages = builder.logNoSubscriberMessages;
  sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
  sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
  throwSubscriberException = builder.throwSubscriberException;
  eventInheritance = builder.eventInheritance;
  executorService = builder.executorService;
}

EventBusBuilder

register()

register

  1. 查找订阅类,即通过register传入的对象里面所有使用Subscribe注释的方法,并将方法信息封装到SubscriberMethod对象中。

  2. 遍历所有的SubscriberMethod对象,调用subscribe方法,每一个方法对应创建一个Subscription对象。

  3. Subscription添加到Map``subscriptionsByEventType中,keyEventType的Class对象。value是订阅该事件的方法的集合。

通过反射我们可以获取到类中Subscribe注释的方法,并将这些信息封装成一个SubscriberMethod对象。

Subscribe

SubscriberMethod

findSubscriberMethods()

findUsingInfo()

findUsingReflectionInSingleClass()

getMethodsAndRelease()

subscribe()

post()

postSingleEvent()

lookupAllEventTypes()

lookupAllEventTypes方法会找到当前事件类型的父类和接口,并且存放到eventTypesCache中,发送当前事件,订阅他的父类的方法也会收消息。

postSingleEventForEventType()

postToSubscription()

  • MAIN

On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread. If not on Android, behaves the same as {@link #POSTING}.

在Android上,订阅者将在Android的主线程(UI线程)中被调用。如果发布线程是 主线程,订阅者方法将被直接调用,阻塞发布线程。否则,该事件 被排队传递(非阻塞)。使用这种模式的订阅者必须快速返回以避免阻塞主线程。 如果不在Android上,其行为与{@link #POSTING}相同。

  • MAIN_ORDER

On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN}, the event will always be queued for delivery. This ensures that the post call is non-blocking.

在Android上,订阅者将在Android的主线程(UI线程)中被调用。与{@link #MAIN}不同。 事件将始终被排队传递。这确保了post的调用是无阻塞的。

  • BACKGROUND

On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single background thread, that will deliver all its events sequentially. Subscribers using this mode should try to return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.

在Android上,订阅者将在一个后台线程中被调用。如果发布线程不是主线程,订阅者方法 将直接在发布线程中被调用。如果发布线程是主线程,EventBus使用一个单一的 后台线程,它将按顺序传递所有事件。使用这种模式的订阅者应尽量 迅速返回以避免阻塞后台线程。如果不在安卓系统上,则始终使用一个后台线程。

  • ASYNC

Subscriber will be called in a separate thread. This is always independent from the posting thread and the main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.

订阅者将在一个单独的线程中被调用。这总是独立于发布线程和 主线程。使用这种模式,发布事件永远不会等待订阅者方法。订阅者方法应该 如果它们的执行可能需要一些时间,例如网络访问,就应该使用这种模式。避免触发大量的 长时间运行的异步订阅者方法,以限制并发线程的数量。EventBus 使用一个线程池来有效地重用来自已完成的异步订阅者通知的线程。

HandlerPoster

postSticky

unregister()

参考

最后更新于