相信大家对 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);
//表示 Event 生成的索引, 初始化的时候 builder.subscriberInfoIndexes 为 null. 所以 indexCount 为 0
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//创建寻找添加了 @Subscribe注解方法的功能类对象, 初始化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<>()
当发送
Event事件的时候, 可以通过subscriptionsByEventType找到对应的订阅者.
subscriptionsByEventType的声明为private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType.
以当前Event事件为key, 也就是消息处理方法的参数的Class
以CopyOnWriteArrayList<Subscription>列表为value. 也就是所有的订阅此事件的订阅者列表.
Subscription对象中又包含了两个属性, 一个是包含了这个Event事件的subscriber订阅者(反射执行对象),一个是SubscriberMethod注解方法的所有属性参数值.
- 分析 2
typesBySubscriber = new HashMap<>()
当注册与反注册事件的时候, 都会对这个
typesBySubscriber进行操作
typesBySubscriber的声明为private final Map<Object, List<Class<?>>> typesBySubscriber
以订阅者为key
以订阅者中订阅的所有Event事的件列表为value
上面两个 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 对象算是创建完成了.
后面将会接着分析注册/解绑, 发送事件等等.








网友评论