EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
EventBus 原理解析
EventBus官网
EventBus Github地址
EventBus的基本用法
- 自定义一个事件类
- 注册事件
- 解除注册
- 发送事件(普通事件、粘性事件)
- 处理事件
自定义一个事件类
public class EventMsg<T> {
private String msg;
private int status;
private T cls;
public EventMsg(String msg, int status, T cls) {
this.msg = msg;
this.status = status;
this.cls = cls;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public T getCls() {
return cls;
}
public void setCls(T cls) {
this.cls = cls;
}
@Override
public String toString() {
return "EventMsg{" +
"msg='" + msg + '\'' +
", status=" + status +
", cls=" + cls +
'}';
}
}
注册事件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册EventBus:getDefault()是一个单例方法,保证当前只有一个EventBus实例
EventBus.getDefault().register(this);
}
解除注册
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
发送事件
普通事件(post)
普通事件是先注册再绑定,就是在发送事件之后先订阅该事件才能收到该事件。
EventBus.getDefault().post(new EventMsg("欢迎来到EvenBus测试页面2", 1, this));
粘性事件(postSticky)
所谓粘性事件,就是在发送事件之后再订阅该事件也能收到该事件。
比如在项目中有这样的需求,在FirstActivity发送事件,到SecondActivity中做事件的处理。如果是使通过EventBus.getDefault.post(xx)发出的,在SecondActivity是接收不到消息的。 主要原因是SecondActivit用于接收消息的EventBus还未完成注册,也就是发布者发了消息,但订阅者还未产生。
EventBus.getDefault().postSticky(new EventMsg("欢迎来到EvenBus测试页面2", 0, this));
处理事件
普通事件
@Subscribe(threadMode = ThreadMode.MAIN)
@Override
public void onEventMessage(EventMsg cls) {
super.onEventMessage(cls);
if (cls.getStatus() == 1)
evenbusBinding.tv.setText(cls.getMsg());
}
粘性事件
/**
* threadMode:线程模式
* ThreadMode.POSTING,默认的线程模式,在那个线程发送事件就在对应线程处理事件,避免了线程切换,效率高。
* ThreadMode.MAIN,如在主线程(UI线程)发送事件,则直接在主线程处理事件;如果在子线程发送事件,则先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件。
* ThreadMode.MAIN_ORDERED,无论在那个线程发送事件,都先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件。
* ThreadMode.BACKGROUND,如果在主线程发送事件,则先将事件入队列,然后通过线程池依次处理事件;如果在子线程发送事件,则直接在发送事件的线程处理事件。
* ThreadMode.ASYNC,无论在那个线程发送事件,都将事件入队列,然后通过线程池处理。
* sticky:是否支持粘性事件,默认为false
*/
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onEventMessage(EventMsg cls) {
msg = cls.getMsg();
}
Subscriber Index
EventBus 注册事件流程,主要是在项目运行时通过反射来查找订事件的方法信息,这也是默认的实现,如果项目中有大量的订阅事件的方法,必然会对项目运行时的性能产生影响。其实除了在项目运行时通过反射查找订阅事件的方法信息,EventBus 还提供了在项目编译时通过注解处理器查找订阅事件方法信息的方式,生成一个辅助的索引类来保存这些信息,这个索引类就是Subscriber Index,其实和 ButterKnife 的原理类似。
Subscriber Index 的核心就是项目编译时使用注解处理器生成保存事件订阅方法信息的索引类,然后项目运行时将索引类实例设置到 EventBus 中,这样当注册 EventBus 时,从索引类取出当前注册类对应的事件订阅方法信息,以完成最终的注册,避免了运行时反射处理的过程,所以在性能上会有质的提高。项目中可以根据实际的需求决定是否使用 Subscriber Index。
具体实现