之前实习的时候就接触过这个框架,近来在弄模块化组件化的事情,感觉EventBus这个框架对于消除模块间依赖还是很有帮助的,顺便来整理一下。
大概的内容分为以下几个部分:
- EventBus简介
- 订阅者的注册/解注册源码分析
- 事件的分发流程源码分析
EventBus简介
EventBus是设计模式中观察者(订阅者)模式的一种实现,为消除组件之间的耦合,实现组件之间的通信提供了一种很好的解决方案,成为一种通用的组件间通信框架。
在整个EventBus框架中,可以把组成成分分为四个部分:事件(Event),总线(EventBus),发布者(Publisher),订阅者(Subscriber)。他们之间的关系大致如图所示。
基本操作介绍
准备工作:在环境中配置依赖:
implementation 'org.greenrobot:eventbus:3.1.1'
在一般的实现中,我们所要做的分为三部分(这里直接拿官方文档内容):
- 定义事件Event:
public static class MessageEvent { /* Additional fields if needed */ }
- 定义事件的订阅者,并向EventBus进行注册:
//定义订阅者
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
//注册
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
//解注册
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
- 发布事件:
EventBus.getDefault().post(new MessageEvent());
五种线程模式
在EventBus中,一种定义了五种线程模式,这代表我们的订阅者可以在选择在这些线程中进行执行。这五种分别如下:
//默认线程,即订阅者处理事件的线程与发布者发布事件的线程相同
@Subscribe(threadMode = ThreadMode.POSTING)
//订阅者在主线程执行响应事件,如果发布者post事件的操作也在主线程,则直接执行
@Subscribe(threadMode = ThreadMode.MAIN)
//订阅者在主线程执行响应事件,区别在于不管如何(发布者post事件的操作是否处于主进程),订阅者都会把事件放入主线程队列中等待被执行
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
//若发布者post事件的操作在主线程,则所有该模式的订阅者都在同一个子线程执行,若发布者post事件的操作所在线程为子线程,则就直接在该线程中处理
@Subscribe(threadMode = ThreadMode.BACKGROUND)
//订阅者会在一个独立的子线程中进行操作
@Subscribe(threadMode = ThreadMode.ASYNC)
Sticky事件
EventBus中还提供了sticky事件,这个事件的特点在于,一旦发布之后,如果有订阅者再次向EventBus注册订阅该事件,订阅者仍然能够接收到最近的一个sticky事件。其中相比于一般的事件,主要是在定义订阅者和发布事件这两步的操作有所区别:
- 定义事件的订阅者:
//定义sticky事件
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(final StickyEvent event) {
if (event.mMessage != null && event.mMessage.length() > 0) {
Log.i(TAG, "onEvent: getMessage" + event.mMessage);
}
}
- 发布事件:
MessageEvent event = new MessageEvent("message");
EventBus.getDefault().postSticky(event);
另外,由于Sticky事件会将接收到的最新的event存储放在EventBus中,所以当我们不需要该事件时,应该将其移除掉,具体操作如下:
private void removeStickyEvent() {
MessageEvent event = EventBus.getDefault().getStickyEvent(MessageEvent.class);
if (event != null) {
EventBus.getDefault().removeStickyEvent(event);
}
}
编译时注解
在之前的EventBus中,当我们进行注册时,EventBus会通过反射的方式找到所有的订阅方法,这样存在的一个问题就是速度较慢。EventBus3中新增的一个特性,就是增加了编译时注解的功能,通过在编译时生成一个Index类,将所有的订阅者类以及其中所有的订阅方法放入到一个Map中,这样在注册的时候就可以通过这个Map找到所有的订阅者,从而加快执行速度。对于使用者来说,如果需要开启这个功能,所需要做的就是在build.gradle中添加如下内容:
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.xyq.EventBusTestIndex' ]
}
}
}
dependencies {
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
到此,EventBus的基本介绍就结束了,接下来对EventBus中的两个关键部分,订阅者的注册/解注册源码,以及事件的分发流程源码进行分析。
订阅者的注册/解注册源码分析
我们的注册是通过调用register()方法来实现的,该方法