关于 EventBus 在开发中经常会选择使用它来进行模块间通信、解耦。平常使用这个库只是很浅显的操作三部曲,register,post,unregister。来达到开发目的。始终有种不明确,模糊的操作感。因此准备对EventBus 进行一个深入,全面的理解,消除模糊,片面感,让以后在使用这个库的时候,有更好的掌握和使用。并记录下来,方便以后查阅。关于 EventBus 会分两章进行记录,本篇文章,是对EventBus的使用做一个全面的介绍,另一篇文章则会对 EventBus 库的源码进行分析,看看他的实现原理是什么样的。
GitHub 地址:https://github.com/greenrobot/EventBus/
为什么会选择使用 EventBus 来做通信?
- 简化了组件间交流的方式
- 对事件通信双方进行解耦
- 可以灵活方便的指定工作线程,通过ThreadMode
- 速度快,性能好
- 库比较小,不占内存
- 使用这个库的app多,有权威性
- 功能多,使用方便
在 app/build.gradle 中添加如下:
implementation 'org.greenrobot:eventbus:3.1.1'
2. 基本使用
EventBus 库中最重要的三个点,分别是 subscriber(订阅者),事件(消息),publisher(发布者)。主要理解这三者的关系即可。
-
subscriber ——> EventBus 的register方法,传入的object对象
-
事件(Event)——> EventBus 的post方法,传入的类型。
-
publisher(发布者)——> EventBus的post方法。
1. 定义事件 创建一个事件类型,消息事件类型可以是string,int等常见类,也可以是自己自定义一个事件类,方便管理。
public class EventMessage {
private int type;
private String message;
public EventMessage(int type, String message) {
this.type = type;
this.message = message;
}
@Override
public String toString() {
return "type="+type+"--message= "+message;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2. 注册、移除注册(接收 Activity) 建议放在 onCreate() 注册和 onDestory() 注销。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//确保之前未订阅过,再调用订阅语句,以免报错
if(!EventBus.getDefault().isRegistered(subscriber)){
EventBus.getDefault().register(subscriber);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消订阅
if (EventBus.getDefault().isRegistered(subscriber)) {
EventBus.getDefault().unregister(subscriber);
}
}
3. 发布事件 (发布 Activity)
EventBus.getDefault().post("SecondActivity发起的通知");
4. 接收事件(接收 Activity)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(String event) {
mTextView.setText(event);
Toast.makeText(this, event, Toast.LENGTH_SHORT).show();
};
3. 粘性事件
一般我们的使用流程为:订阅事件—》发送事件—》接收处理事件。
那如果现在希望发送事件—》订阅事件—》接收处理事件,这可以实现吗?答案是可以的。
EventBus提供的粘性事件便可实现这一场景。
1. 使用步骤 使用步骤和普通事件的基本一样,但有两点需注意:
- 注册事件接收的操作(EventBus.getDefault().register(this);)需在控件初始化后再执行,否则会接收不到,这里建议放在onStart的生命周期中执行。
- 事件的发送调用的是postSticky(event),事件处理函数需声明@Subscriber(sticky = true)。
//事件发送方
//发送粘性事件
EventBus.getDefault().postSticky(new MovieEvent(1));
//事件接收处理方
//发送完粘性事件后再进行订阅事件
EventBus.getDefault().register(this);//注册事件接收
//接收处理订阅前发出的粘性事件
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void handleEvent(MovieEvent event) {
//处理事件
int count = event.getCount();
}
2. 使用场景 ActivityA 跳转到 ActivityB,并将 Movie 对象传递过去。
//ActivityA中的代码
Movie movie = new Movie();
//发送粘性事件,传送movie
EventBus.getDefault().postSticky(movie);
//跳转到ActivityB
startActivity(new Intent(this, ActivityB.class));
//ActivityB中的代码
//订阅事件
EventBus.getDefault().register(this);
//获取订阅前ActivityA发送的粘性事件
@Subscribe(sticky = true)
public void getDataFromOtherActivity(Movie movie) {
//得到ActivityA的Movie对象,进行具体操作。
}
4. 简单封装
public class EventBusManager {
//开启Index加速
public static void openIndex() {
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
}
//订阅事件
public static void register(Object subscriber) {
if(!EventBus.getDefault().isRegistered(subscriber)){
EventBus.getDefault().register(subscriber);
}
}
//取消订阅
public static void unregister(Object subscriber) {
if (EventBus.getDefault().isRegistered(subscriber)) {
EventBus.getDefault().unregister(subscriber);
}
}
//终止事件继续传递
public static void cancelDelivery(Object event) {
EventBus.getDefault().cancelEventDelivery(event);
}
//获取保存起来的粘性事件
public static T getStickyEvent(Class classType){
return EventBus.getDefault().getStickyEvent(classType);
}
//删除保存中的粘性事件
public static void removeStickyEvent(Object event) {
EventBus.getDefault().removeStickyEvent(event);
}
//发送事件
public static void postEvent(Object event){
EventBus.getDefault().post(event);
}
//发送粘性事件
public static void postStickyEvent(Object event) {
EventBus.getDefault().postSticky(event);
}
}
5. 混淆
在 proguard-rules.pro 文件中添加以下内容进行混淆配置
#EventBus开始
-keepattributes *Annotation*
#如果使用了EventBus index进行优化加速,就必须加上这个
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe ;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
#如果使用了Async类型的线程
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
(java.lang.Throwable);
}
#EventBus结束