概述
EventBus是一个开源库,它使用的是发布/订阅模式来实现组件之间的通信,相对于广播机制,handler机制等,其所需要的代码更少,耦合度更低,下面是一张官方的图说明其工作方式。
从图中我们可以看出EventBus的3个主体内容
- Publisher(发布者),在任何线程都可以发布信息
- Subsciber(订阅者),只需要在函数上加上注解@Subscriber就可以接受到订阅消息
- Event(事件),可以是任何类型
使用
1、引入依赖
implementation 'org.greenrobot:eventbus:3.1.1'
2、定义事件
利用EventBus发送的事件的类型可以很多,String,int …,自定义Message等,这里我们自定义一个类。
public class EventMsg {
public String message;
public int type;
public EventMsg(String message, int type) {
this.message = message;
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
3、发布和订阅
首先需要注册EventBus,一般在onStart()里面注册,在onStop()里面取消注册,也可以按照自己的需求在onCreate(),onDestory()里面进行注册和取消注册都可以。
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
消息发布,这里把它放在一个按钮点击事件里面
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
EventMessage msg = new EventMessage(1,"eventbusmsg");
// 获取一个EventBus对象,然后把消息发送出去
EventBus.getDefault().post(msg);
}
});
thread.start();
}
});
下面是订阅消息,在方法上加上@Subscribe注解
// 接受事件消息1
@Subscribe(threadMode = ThreadMode.MAIN,priority = 1)
public void onReceiveMsg(EventMessage msg){
Log.d(TAG, "onReceiveMsg: 当前线程:"+Thread.currentThread().getName());
}
// 接受事件消息2
@Subscribe(threadMode = ThreadMode.MAIN,priority = 2,sticky = false)
public void getEventMsg(EventMessage msg){
Log.d(TAG, "getEventMsg: "+Thread.currentThread().getName());
}
这里我写了两个接受消息的函数,主要是为了做对比,对订阅函数有几个要求
1、必须使用Subscribe进行注解
2、只能有一个参数
3、必须是public的,不能是static和abstract的
Subscribe中有3种类型的参数,下面一一介绍一下。
ThreadMode处理函数的线程模式
-
POSTING
默认,事件处理线程和发布线程在同一个线程中
-
MAIN
时间处理线程是主线程,因此不能处理耗时操作
-
BACKGROUND
处理线程是后台线程,不能进行UI操作,如果事件的发布线程是主线程,那么处理函数将开启一个后台线程,如果发布线程是一个后台线程,那么处理函数就使用该线程。
-
ASYNC
无论发布事件的是哪个线程,处理函数都会创建一个新线程。
priority优先级
优先级高的函数先收到消息,这和广播类似,需要注意的是,优先级起作用要求其线程模式是一样的,如果一个是MAIN,一个是ASYNC,那即便是ASYNC指定了更高的优先级还是MAIN先收到。
Sticky
sticky是一个boolean型的参数,默认值是false,表示不启用sticky特性。那么sticky特性是什么呢?我们之前说的EventBus事件传递的例子的时候,我们都是先对订阅者(Subscriber)进行先注册的,然后再post事件的。那sticky的作用是在先post事件,后对订阅者注册这种开发场景的支持的,不过需要选择postStricky()函数。
private View.OnClickListener mGoListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: post");
EventMessage message = new EventMessage(233, "post message before");
EventBus.getDefault().postSticky(message);
}
};
private View.OnClickListener mRegisterListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: start register" );
EventBus.getDefault().register(MainActivity.this);
}
};
我们先使用postSticky发布了一个消息,才进行注册,结果也可以收到消息。
使用EventBus通信
利用EventBus还可以在frament之间,fragment个Activity之间通信,只要是注册过的并且存活的fragment和Activity都能收到Event Bus发出的消息。