EventBus简介
EventBus是一个Android和java的开源库,使用发布者/订阅者模式进行松散耦合。EventBus只需要几行代码即可实现与分离类的集中通信-简化代码,消除依赖关系,并加速应用程序开发。
使用EventBus的好处:
- 简化了组件之间的通讯
- 将事件发送者和接受者进行了分离
-适用于UI工件(例如:Activity、Fragment)和后台线程 - 避免复杂切容易出错的依赖关系和生命周期问题
- 快 ;专门针对高性能进行了优化
- 小; <50kb
- 具有线程切换,用户优先级等高级功能
在日常的开发当中我们也用到了一些其它的消息传递方式,对比参照Android消息传递BroadCast、Handler和EventBus优缺点
1.1三个角色
- Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
-
Subscriber:事件订阅者,在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模式,默认是
POSTING
。 -
Publisher:事件发布者,可以在任意线程里发布事件。一般情况下,使用
EventBus.getDefault()
就可以得到一个EventBus对象,然后再调用post(object)
方法即可。
1.2 四种线程模式
EventBus3.0有四种线程模式,分别指定了事件订阅者的不同工作线程,分别是:
- POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一线程。
- MAIN:表示事件的处理函数在UI线程(使用不要做耗时操作)
- BACKGROUND:表示事件的处理函数在后台线程。如果事件的发布线程是主线程,那么事件处理函数则会开启一个后台线程,如果事件的发布线程本来就在后台线程,那么事件的处理函数就会使用该线程。
- ASYNC: 异步。表示无论事件的发布线程在哪,事件的处理函数都会创建一个新的自线程来运行操作。
EventBus简单使用
2.1 引入依赖
在使用之前要引入依赖:
implementation 'org.greenrobot:eventbus:3.1.1'
2.2定义事件
EventBus的订阅者和发布者对于关系的匹配是根据事件来进行的,就是处理函数的参数类型。如果逻辑足够简单,使用时也足够肯定,可以直接使用基本数据类型,无需专门定义。
不过一般还是建议定义一个封装对象。在程序内部使用,避免订阅混淆。
public class MessageWrap {
public final String message;
public static MessageWrap getInstance(String message) {
return new MessageWrap(message);
}
private MessageWrap(String message) {
this.message = message;
}
}
2.3发布事件
在程序任意位置都可以使用如下代码发送定义好的事件
EventBus.getDefault().post(mMessageWrap);
2.4 事件订阅
如果想在Activity或Fragment中接收到事件,必须进行订阅EventBus.getDefault().register(this);
和取消订阅EventBus.getDefault().unregister(this);
订阅和取消订阅的时机根据需求确定;如果注册了订阅事件则必须存在@Subscribe注解的处理函数,不然会报错
public class EventBusTestBus extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGetMessage(MessageWrap message) {
//TODO 根据message进行处理
}
}
EventBus高级功能
3.1 黏性事件
所谓的黏性事件,就是之发送了该事件之后再订阅依然能够接收到事件。关键字sticky
;使用黏性事件非常简单,只需注意两处地方
实现处理函数时增加sticky=true
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onGetStickyEvent(MessageWrap message) {
String txt = "Sticky event: " + message.message;
getBinding().tvStickyMessage.setText(txt);
}
发布事件时使用postSticky
替换post
EventBus.getDefault().postSticky(mMessageWrap);
3.2 优先级
说到优先级很容易就能想到另外一种消息传递方式BroadCase。实际上也非常相似,使用priority
来指定优先级,priority是一个整数类型的值,值越大优先级越高,默认0。同样可以在高优先级的处理函数里停止事件继续分发。
这里需要特别注意:
- 只有当前订阅方法使用相同的
threadMode
参数的时候,它们的优先级才会与priority
指定的值一致; - 只有当订阅方法的
threadMode
参数为POSTING
的时候,它才能停止事件的继续分发
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
public void onGetStickyEvent(MessageWrap message) {
//TODO message处理
if (stopDelivery) {
// 终止事件的继续分发
EventBus.getDefault().cancelEventDelivery(message);
}
}