这可能是最详细的 EventBus 源码分析01 - EventBus 对象的创建
这可能是最详细的 EventBus 源码分析02 - EventBus 的注册(上篇)
这可能是最详细的 EventBus 源码分析03 - EventBus 的注册(下篇)
这可能是最详细的 EventBus 源码分析04 - 事件的发送与执行
这可能是最详细的 EventBus 源码分析05 - Subscriber Index
相信大家对 EventBus
都是非常熟悉了. 做 Android
开发的同学基本都使用过这个框架. 它的用法基本分为以下几个步骤
- 定义事件
event
. - 通过注解, 准备订阅者.
- 订阅者同时需要在事件总线上注册和注销自己.
(register, unregister)
- 发送事件.
- 任何匹配到该事件的订阅者, 都将会接收到这个事件.
这里就不在说明 EventBus
的具体用法了, 那么在接下来, 将会对 EventBus
的源码及内部原理进行学习分析.
(这里分析的 EventBus
源码版本为 3.2.0
)
1. EventBus 对象的构建
在使用 EventBus
的时候, 无论是注册/反注册或者是发送事件都会先调用 EventBus.getDefault()
这个方法. 那么就以这个方法为入口来进行分析.
1.1 EventBus.getDefault()
/** 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
对象. 那么接着进入到 EventBus
的构造函数中.
1.2 EventBus()
public EventBus() {
this(DEFAULT_BUILDER);
}
是不是发现和我们平时写的单例有点不同呢? 我们平时写的单例, 构造方法一般都是 private
的. 但是这里却是 public
.
那么 EventBus
有了单例后, 为什么还要把构造函数设置为 public
呢 ? 是不是有特别的用意呢 ?
原来啊,
EventBus
这样设计是有原因的. 我们要知道EventBus
在我们的整个代码当中, 并不是仅仅只有一条总线的. 还会有其他的EventBus
总线. 那么我们的订阅者, 就可以注册到不同的EventBus
下. 然后通过不同的EventBus
来发送数据给订阅者.而我们需要注意的是, 不同的
EventBus
发送的数据, 是相互隔离的. 订阅者只会收到注册到该线程上的数据.
接着看. 构造函数中又调用了 this(DEFAULT_BUILDER)
, 点击 DEFAULT_BUILDER
可以知道就是 EventBusBuilder
.
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
看到这里可以猜到 EventBus
最终还是通过构建者模式来进行对象的创建的. 下面跟进到 EventBus(EventBusBuilder builder)
构造方法中.
1.3 EventBus(EventBusBuilder builder)
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
//分析 1
subscriptionsByEventType = new HashMap<>();
//分析 2
typesBySubscriber = new HashMap<>();
//黏性事件: 发送事件之后, 再订阅该事件也能收到该事件,跟黏性广播类似. 使用支持并发的 ConcurrentHashMap 创建
stickyEvents = new ConcurrentHashMap<>();
//分析 3
//创建实现了 MainThreadSupport 接口的内部类 AndroidHandlerMainThreadSupport, 并传入MainLooper.
mainThreadSupport = builder.getMainThreadSupport();
// 分析 4
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
//创建后台处理的 poster
backgroundPoster = new BackgroundPoster(this);
//创建异步处理的 poster
asyncPoster = new AsyncPoster(this);
//如果未使用自定义索引类, 初始化的时候 builder.subscriberInfoIndexes 为 null. 所以 indexCount 为 0
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//若未使用自定义索引类, subscriberInfoIndexes 为 null. 所以初始化subscriberMethodFinder 对象时传入参数为 null, false, false.
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);
//调用事件处理方法的时候, 发生异常后是否打印异常信息日志, 默认为 true
logSubscriberExceptions = builder.logSubscriberExceptions;
//当没有订阅者订阅当前 Event 事件的时候, 是否需要打印日志, 默认为 true
logNoSubscriberMessages = builder.logNoSubscriberMessages;
//当调用事件处理方法的时候如果出现异常, 是否需要发送 SubscriberExceptionEvent 事件, 默认为 true
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
//当没有事件处理方法时, 是否需要发送 NoSubscriberEvent 事件, 默认为 true
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
//是否需要抛出 SubscriberException 异常, 默认为 false
throwSubscriberException = builder.throwSubscriberException;
//与Event 有继承关系的是否都需要发送, , 默认为 true
eventInheritance = builder.eventInheritance;
//构建线程池.默认构建的为 Executors.newCachedThreadPool();
executorService = builder.executorService;
}
由于属性字段太多, 这里只挑了几个比较重要, 并且有代表性的来分析一下.
- 分析 1
subscriptionsByEventType = new HashMap<>()
subscriptionsByEventType
的声明为private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType
.
以当前 Event
事件为 key
, 以 CopyOnWriteArrayList<Subscription>
列表为 value
. 关系如下图显示
这个 map
的目的是为了在发送 Event
事件的时候, 总能根据此 map
找到所有的订阅记录,再根据订阅记录中的订阅方法包装类处理此事件的线程模型, 将此事件分发到对应的线程, 利用反射, 调用订阅者对此事件的事件处理方法,完成事件的发布与处理.
- 分析 2
typesBySubscriber = new HashMap<>()
typesBySubscriber
的声明为private final Map<Object, List<Class<?>>> typesBySubscriber
以订阅者为 key
, 以订阅者中订阅的所有 Event
事件类型列表为 value
当注册与反注册事件的时候, 都会对这个 typesBySubscriber
进行操作
上面两个 map
的数据都是各个线程都可以访问的,因此访问的时候要对这两个 map
加锁.
- 分析 3
mainThreadSupport = builder.getMainThreadSupport()
调用了EventBusBuilder.getMainThreadSupport()
方法, 现在进去看一下这个方法内部做了什么.
MainThreadSupport getMainThreadSupport() {
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (AndroidLogger.isAndroidLogAvailable()) {
Object looperOrNull = getAndroidMainLooperOrNull();
return looperOrNull == null ? null : new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
} else {
return null;
}
}
static Object getAndroidMainLooperOrNull() {
try {
return Looper.getMainLooper();
} catch (RuntimeException e) {
// Not really a functional Android (e.g. "Stub!" maven dependencies)
return null;
}
}
看到
getMainThreadSupport
方法返回的是MainThreadSupport
, 而变量mainThreadSupport
在EventBusBuilder
并没有找到给它赋值的地方. 那么就是为null
. 执行else if
方法.AndroidLogger.isAndroidLogAvailable()
这里返回的为true
, 接着调用getAndroidMainLooperOrNull ()
方法获取到主线程的looper
. 接着创建实现了MainThreadSupport
接口的内部类AndroidHandlerMainThreadSupport
传入主线程looper
并返回.
接着进入到 MainThreadSupport.AndroidHandlerMainThreadSupport
看他的构造方法.
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
public AndroidHandlerMainThreadSupport(Looper looper) {
this.looper = looper;
}
@Override
public boolean isMainThread() {
return looper == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, looper, 10);
}
}
}
看到构造方法内只是将上面传入的主线程
looper
保存下来.
那么分析 3 的流程就走完了, 总的来说就是创建实现了 MainThreadSupport
接口的内部类 AndroidHandlerMainThreadSupport
, 并在 AndroidHandlerMainThreadSupport
中保存了主线程的 looper
- 分析 4
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
创建在主线程处理的 poster
拿到刚才创建的AndroidHandlerMainThreadSupport
对象调用它的createPoster (EventBus eventbus)
方法. 并传入当前Event
事件.
在上面贴出来的AndroidHandlerMainThreadSupport
类中的createPoster
方法中看到就是new
了一个HandlerPoster
对象, 并传入当前Event
事件与主线程looper
, 以及一个数值 10.
接着进入到 HandlerPoster
看一下, 都初始化了什么.
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
...
}
@Override
public void handleMessage(Message msg) {
...
}
}
看到 HandlerPoster
继承自 Handler
重写了 handleMessage
方法来处理 Event
事件, 同时实现了 Poster
接口的 enqueue
方法将 Event
事件入队. 这里只看构造方法, 这两个方法后面会有分析到.
在构造方法内, 看到将我们传入进来
Event
事件与主线程的Looper
以及那个数字 10 都赋值给了自身的变量.
private final PendingPostQueue queue
: 存放要执行的Event
事件的一个队列. 是一个双向链表.后面会有分析.
private final int maxMillisInsideHandleMessage
: 判断任务执行的最大时间, 大于这个时间表示超时.
private final EventBus eventBus
: 当前的Event
事件
private boolean handlerActive
: 标识当前Handler
是否是活动状态.
那么到这里在分析 4 中, 就完成了主线程 mainThreadPoster
的创建.
backgroundPoster
后台处理的 Poster
与 asyncPoster
异步处理的 Poster
与之类似, 不同的是, 他们没有继承 Handler
, 而是实现了 Runnable
接口. 这里就不再对这两个类进行分析.
剩下的在构造函数里都说明了含义, 就不再一一查看分析了. 到这里一个 EventBus
对象算是创建完成了.
后面将会接着分析注册/解绑, 发送事件等等.