前言
- 在
Android开发中,EventBus事件总线机制十分常用; - 今天,我将整理
EventBus详细的使用教程,希望能帮上忙。
目录
1. EventBus 机制简介
- 定义
一套Android/Java事件发布 / 订阅框架,由 greenrobot 团队开源
EventBus版本变更示意图
- 作用
在组件 / 线程间通信的应用场景中,将数据或事件传递给对应的订阅者,从而实现事件传递
EventBus原理示意图
- 为什么要使用
EventBus?
在 Android 组件 / 线程间通信的应用场景中,EventBus 比传统的接口监听、Handler、Executors、LocalBroadcastManager更简洁可靠,具体描述如下:
示意图
- 总结
使用EventBus框架的原因:- 使用事件总线框架,实现事件发布者与订阅者松耦合;
- 提供了透明线程间通信,隐藏了发布线程与订阅线程间的线程切换。
2. 相关概念
关于EventBus机制的相关概念如下:
EventBus相关概念示意图
3. 使用步骤
3.1 步骤1:添加依赖
- 在module级
build.gradle中添加依赖:
dependencies {
def eventbus_version = '3.2.0'
implementation "org.greenrobot:eventbus:$eventbus_version"
}
- 使用
编译时索引时,还需要依赖注解处理工具,纯Java项目和Kotlin使用的工具不同:-
Java项目使用annotationProcessor工具 -
Kotlin项目使用kapt工具
-
// Java:
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.have.a.good.MyEventBusAppIndex' ]
}
}
}
}
dependencies {
def eventbus_version = '3.2.0'
implementation "org.greenrobot:eventbus:$eventbus_version"
annotationProcessor "org.greenrobot:eventbus-annotation-processor:$eventbus_version"
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied
dependencies {
def eventbus_version = '3.2.0'
implementation "org.greenrobot:eventbus:$eventbus_version"
kapt "org.greenrobot:eventbus-annotation-processor:$eventbus_version"
}
kapt {
arguments {
arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex')
}
}
3.2 步骤2:准备订阅者
-
订阅者需要实现订阅方法,并使用@Subscribe注解修饰,具体描述如下:
准备订阅者
- 举例:
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show(); } - 五种
线程模式具体描述如下:
五种线程模式
3.3 步骤3:注册与注销
- 在发布事件之前,需要先
注册订阅者;在订阅者生命周期结束时,需要注销订阅者,具体描述如下:
注册与注销
- 举例:
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
3.4 步骤4:发布事件
- 调用
EventBus#post(Object)发布普通事件 - 调用
EventBus#postSticky(Object)发布粘性事件
发布事件
- 举例:
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
-
粘性事件具体描述如下:
粘性事件
- 举例:
// 1. 订阅
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
// 2. 发布
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
// 3. 获取粘性事件
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
if(stickyEvent != null) {
// 4. 移除粘性事件
EventBus.getDefault().removeStickyEvent(stickyEvent);
// do something.
}
// 5. 移除粘性事件
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
if(stickyEvent != null) {
// do something.
}
4. 编译时索引
-
EventBus 3.x相较于EventBus 2.x最大的改良就是编译时索引,注解生成器的源码可查看:EventBus 注解处理器源码,具体描述如下:
编译时索引
- 为了生成
编译时索引,首先需要在build.gradle中配置索引文件,例如:
kapt {
arguments {
arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex')
}
}
- 编译时,
注解处理器将解析@Subscribe注解修饰的方法,生成索引类(MyEventBusAppIndex),在运行时构建时添加索引,例如:
EventBus eventBus = EventBus.builder()
.addIndex(new MyEventBusAppIndex())
.build();
- 索引类配置只对当前
module有效,因此需要在每个包含订阅者的module的build.gradle中添加索引类配置,例如:
// App module
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied
kapt {
arguments {
arg('eventBusIndex', 'com.have.a.good.MyEventBusAppIndex')
}
}
dependencies {
...
kapt "org.greenrobot:eventbus-annotation-processor:3.2.0"
implementation project(path: ':base')
}
// Lib module
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied
kapt {
arguments {
arg('eventBusIndex', 'com.have.a.good.MyEventBusLibIndex')
}
}
dependencies {
...
api 'org.greenrobot:eventbus:3.2.0'
kapt "org.greenrobot:eventbus-annotation-processor:3.2.0"
implementation project(path: ':base')
}
以上配置将生成两个索引类文件,MyEventBusAppIndex类只包含App Module中的订阅者索引,而MyEventBusLibIndex只包含Lib Module中的订阅者索引。
5. 构建者模式
-
构建者模式(Builder Pattern)可以说是开源库的标配了,EventBus自然也不例外;
-
EventBus类封装了所有的API,调用EventBus.getDefault()获得默认的EventBus实例; -
EventBusBuilder类用于构建EventBus实例,具体如下:- 异常处理配置
配置项 描述 默认值 logSubscriberExceptions 订阅函数执行有异常时,打印异常信息 true sendSubscriberExceptionEvent 订阅函数执行有异常时,发布SubscriberExceptionEvent事件 true throwSubscriberException 订阅函数执行有异常时,抛出SubscriberException false logNoSubscriberMessages 事件无匹配订阅函数时,打印信息 true sendNoSubscriberEvent 事件无匹配订阅函数时,发布NoSubscriberEvent true - 注册者索引配置
配置项 描述 默认值 ignoreGeneratedIndex 忽略订阅者索引 false addIndex(SubscriberInfoIndex index) 添加订阅者索引 无 - 事件订阅配置
配置项 描述 默认值 eventInheritance 是否触发父类事件订阅函数 true executorService(ExecutorService executorService) 线程池 Executors#
newCachedThreadPool()strictMethodVerification 是否严格验证订阅函数签名 true skipMethodVerificationFor(Class<?> clazz) 跳过方法签名验证 无
6. 混淆
- 混淆是版本发布的必备环节,若还不了解,请务必阅读文章:
《Android | 代码混淆到底做了什么?》 -
EventBus需要配置以下混淆规则:
-keepattributes *Annotation*
// keep住所有被Subscribe注解标注的方法
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
这里着重讲解一下注释部分,因为生成编译时索引是在代码混淆之前进行的,而代码混淆之后类名和方法名都不一样了,这样就会导致运行时找不到编译时索引中记录的方法名了,因而得keep住所有被@Subscribe注解标注的方法。
- 如果使用了
AsyncExecutor,还需要配置混淆规则:
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
7. 总结
- 本文对
EventBus的使用进行了全面讲解 - 下面我将继续深入讲解
EventBus源码分析,感兴趣的同学可以点个关注!
推荐阅读
- 开发者 | 浅析App社交分享的5种形式
- 开发者 | WGS84、GCJ-02、BD-09都是什么鬼?
- 开发者 | 几个提高远程办公效率的小建议
- 开发者 | 那些令人“奔溃”的 UI 验收
- Dart | 彻底理解Dart中的库与访问可见性
- Android | 代码压缩、优化与混淆 — ProGuard与R8
- Android | InputManagerService 与输入事件采集
2020 永远不要放弃希望,祝愿大家都能够平安健康!武汉加油!









网友评论