一、简介
1、EventBus是一种用于Android的事件发布-订阅总线,它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。
2、事件可以是任意类型,EventBus会根据事件类型进行全局的通知,在EventBus 3.0之前接收事件必须定义以onEvent
开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING
3、四种线程模型:
POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程
ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作
二、EventBus的使用(包含粘性事件)
1、在build.gradle中添加依赖
implementation 'org.greenrobot:eventbus:3.1.1' //eventbus事件
2、在需要接收事件的类中,初始化中定义,销毁时一并销毁,这里已service为例
在启动service的onStartCommand类中注册时:
`@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
EventBus.getDefault().register(this);
return super.onStartCommand(intent, flags, startId);
}`
3、定义接收事件的方法
注:在接收和发送事件时我定义了事件类和事件类型的一个类,在后面会贴出代码
也会给记录不定义任何类的发送和接收
同时记录下自己在activity中发送事件在service中接收时的bug
不定义事件类时的接收
@Subscribe(threadMode = ThreadMode.MAIN)//处理一般事件
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//处理粘性事件
public void receiveStatus(String event) { {
} }
定义事件类时的接收:
`//@Subscribe(threadMode = ThreadMode.MAIN)//处理一般事件
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//处理粘性事件
public void receiveStatus(JPushEvent event) {
if(EventType.SUCCESS_PERMISSIONS.equals(event.getType())){
//开始定位
//hasPermission = true;
}
}`
注:这里使用了粘性事件,因为这里的事件在启动该service的acvitivy中发布,不能保证发布事件时该订阅者已经注册
粘性事件稍后会详细讲
4、发送事件
在任何需要发送事件的地方进行发送,这里已调用该service的Activity为例,同样
也记录不定义事件类和定义事件类的发送:
不定义时发送:
EventBus.getDefault().post("发送的数据"));
定义事件类时:
在该activity的onCreate方法中:
`@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MainActivity.this, LocationService.class);
startService(intent); `
`EventBus.getDefault().postSticky(new JPushEvent(new Object(), EventType.SUCCESS_PERMISSIONS));//发送粘性事件//
`EventBus.getDefault().post(new JPushEvent(new Object(), EventType.SUCCESS_PERMISSIONS));//发送一般事件 }`
在这里,我一开始就是以为先启动了service再发送事件在service中肯定能接收到,但是其实启动service和发送事件并不在同一个线程中,所以并不能保证事件发送之前在service中已经注册了订阅者
所以用粘性事件,发送一般事件也写了
5、注销事件:
为例不使内存泄漏导致最终内存溢出。在注册事件的service中的onDestroy()方法中来注销事件,
粘性事件和一般事件的注册方法一致,注销方法稍微不一致,
@Overridepublic void onDestroy() { super.onDestroy();
EventBus.getDefault().unregister(this);//注销一般事件
EventBus.getDefault().removeAllStickyEvents();//注销粘性事件
}
```
在这个例子中使用的事件类:
public class JPushEvent {
private Object message;
private String type;
public JPushEvent(Object message,String type) {
this.message = message;
this.type = type;
}
public Object getMessage() {
return message;
}
public void setMessage(Object message) {
this.message = message;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}}
//同时为类型也定义了一个类在下方代码块中:(可以不使用)
/** * 事件类型定义 */
public class EventType {
public static final String JPUSH_EVENT = "JPUSH_EVENT";//极光推送接收事件
public static final String LOCATION_EVENT = "LOCATION_EVENT";//获取位置信息事件
public static final String SUCCESS_PERMISSIONS ="SUCCESS_PERMISSIONS";//获取权限成功事件}
```
三、粘性事件和优先级
所谓的黏性事件,就是指发送了该事件之后再订阅者依然能够接收到的事件,就像我遇到的问题一样
粘性事件和一般事件有两点不同:
1、事件的订阅:
`@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)`
2、事件的注销:
`EventBus.getDefault().removeAllStickyEvents();`
优先级:
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
优先级越高越先接收到事件