EventBus使用及解析
在我们刚学Android不久,就会学到用接口回调来异步通知事件。写起来也算顺手,但是接口回调需要不断地设置listener,耦合性较大,当项目越来越复杂,接口回调的传值会形成一张错综复杂的网,有这样使用经历的人就会深有感触。于是,就可以使用EventBus的事件传递方法,在发送着和接收者完全解耦,传递接收范围广,接下来就学习怎样使用Eventbus。
事件产生过程
流程示意图EventBus的三要素
Event:事件,可以是任意类型的对象。
Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。
使用步骤
引入库
implementation 'org.greenrobot:eventbus:3.0.0'
这里可以看到EventBus.getDefault()内部调用的是懒汉式的单例获取Eventbus对象方法。
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
创建发送的实体类,根据发送者的实体类和接收者的实体类相匹配来看是否接收事件。
public class PostMsg {
private int num;
private String title;
public PostMsg(int num, String title) {
this.num = num;
this.title = title;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
在任意需要发送事件的地方发送消息,对,发送就是这么简单:
EventBus.getDefault().post(new PostMsg(100,"这里是标题"));
接收消息的地方需要在onCreate()方法中进行注册
EventBus.getDefault().post(this);
在onDestroy()方法中取消注册(避免内存泄漏)
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
接收消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PostMsg postMsg){
Toast.makeText(getApplicationContext(),postMsg.getNum() + " " + postMsg.getTitle(),Toast.LENGTH_LONG).show();
}
线程模式
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
POSTING:订阅者方法将在发布事件所在的线程中被调用。是默认的线程模式,该模式不会切换线程,意味着最少的性能开销。可能会发生下主线程。
MAIN:订阅者方法将在主线程中被调用。
BACKGROUND:订阅者方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么订阅者方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程
ASYNC:订阅者方法将在一个单独的线程中被调用,该模式可用来执行耗时操作。
粘性事件
当有需求需要发送消息,所有注册过的Activity都能收到。但是此时只有一部分Activity创建了,那么此时发出消息,未创建的Activity就接收不到消息。粘性事件就解决了该问题。通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,直到被 removeStickyEvent 删除掉。
发布粘性事件
EventBus.getDefault().postSticky(new PostMsg(100,"这里是标题"));
接收粘性事件
@Subscribe(sticky = true)
public void onEventMainThread(PostMsg postMsg){
}
移除指定粘性事件
//移除某种类型粘性事件
EventBus.getDefault().removeStickyEvent(ThreadMode.xxx);
//移除某种对象粘性事件
EventBus.getDefault().removeStickyEvent(object);
//移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();