EventBus是一款针对Android优化的发布/订阅事件总线。能够替代广播、startActivityForResult
、Handler
、异步回调等来实现各组件间、组件与后台线程间的通讯。它的优势是开销小,代码更优雅,以及将发送者和接收者解耦。javascript
一般咱们在使用EventBus
的时候都是直接须要接收通讯的Activity/Fragment
中经过EventBus.getDefault().register(this)
订阅事件,在须要发起通讯的逻辑直接调用EventBus.getDefault().post(Object event)
来发布事件。可是要是一个项目中有不少地方都使用EventBus
来通讯,好比从新登陆后更新各个页面的登陆状态,或者是接收到通知更新消息提示等,都这样直接使用的话代码重复率很高,而且呢,若是之后升级或者更换EventBus
时,各个地方都要修改,这就比较麻烦了。所以我通常是将EventBus
的发布和订阅封装到BaseActivity/BaseFragment
中。java
在Gradle中添加EventBus
依赖:git
compile 'org.greenrobot:eventbus:3.0.0'复制代码
封装一下EventBus
的订阅、取消订阅、发布等方法:github
public class EventBusUtil {
public static void register(Object subscriber) {
EventBus.getDefault().register(subscriber);
}
public static void unregister(Object subscriber) {
EventBus.getDefault().unregister(subscriber);
}
public static void sendEvent(Event event) {
EventBus.getDefault().post(event);
}
public static void sendStickyEvent(Event event) {
EventBus.getDefault().postSticky(event);
}
// 其余
}复制代码
在BaseActivity/BaseFragment
中的onCreate
和onDestroy
方法中订阅和取消订阅,这里添加了一个isRegisterEventBus()
方法,默认返回false
,即不订阅EventBus
,子类Activity/Fragment
若是须要订阅的话复写这个方法并返回true
便可。异步
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (isRegisterEventBus()) {
EventBusUtil.register(this);
}
}
/** * 是否注册事件分发 * * @return true绑定EventBus事件分发,默认不绑定,子类须要绑定的话复写此方法返回true. */
protected boolean isRegisterEventBus() {
return false;
}
@Override
public void onDestroy() {
super.onDestroy();
if (isRegisterEventBus()) {
EventBusUtil.unregister(this);
}
}复制代码
定义事件Event
:ide
public class Event<T> {
private int code;
private T data;
public Event(int code) {
this.code = code;
}
public Event(int code, T data) {
this.code = code;
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}复制代码
经过泛型<T>
指定事件通讯过程当中的数据类型,code
为事件码,使用的时候给不一样的事件类型指定不一样的code
。post
在BaseActivity\BaseFragment
中添加接收到EventBus
的方法:优化
/** * 是否注册事件分发 * * @return true绑定EventBus事件分发,默认不绑定,子类须要绑定的话复写此方法返回true. */
protected boolean isRegisterEventBus() {
return false;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBusCome(Event event) {
if (event != null) {
receiveEvent(event);
}
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onStickyEventBusCome(Event event) {
if (event != null) {
receiveStickyEvent(event);
}
}
/** * 接收到分发到事件 * * @param event 事件 */
protected void receiveEvent(Event event) {
}
/** * 接受到分发的粘性事件 * * @param event 粘性事件 */
protected void receiveStickyEvent(Event event) {
}复制代码
根据本身项目的需求,在订阅了EventBus
的Activity/Fragment
中复写receiveEvent(Event event)
或receiveStickyEvent(Event event)
来处理接收到事件后的逻辑。ui
这里也能够不用在BaseActivty/BaseFragment
中添加接受事件的方法(由于添加了事后不能肯定的子类的Event
泛型)。那么就直接在订阅的Activity/Fragment
中给接收事件的方法添加EventBus
对应的事件接受注解,并指定参数Event的泛型。this
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventReceived(Event<User> event) {
if (event != null && event.getCode() == C.EventCode.C) {
User user = event.getData();
}
}复制代码
在给定Event
的code
的时候最好在常量池中定义一个类专门用来定义不一样类型的EventBus
的code
,这样在接收到EventBus
的地方能够根据这些code
值来判断Event
的来源。
public final class C {
// EventBus Code
public static final class EventCode {
public static final int A = 0x111111;
public static final int B = 0x222222;
public static final int C = 0x333333;
public static final int D = 0x444444;
// other more
}
}复制代码
使用示例:
在MainActivity
中复写isRegisterEventBus()
并返回true
注册EventBus
,复写receiveEvent(Event event)
接收发布的事件。
@Override
protected boolean isRegisterEventBus() {
return true;
}
@Override
protected void receiveEvent(Event event) {
// 接受到Event后的相关逻辑
switch (event.getCode()) {
case C.EventCode.A:
Log.d("EventBus", "接收到A类型的Event");
break;
case C.EventCode.B:
Log.d("EventBus", "接收到B类型的Event");
break;
case C.EventCode.C:
Log.d("EventBus", "接收到B类型的Event,携带User");
User user = (User) event.getData();
break;
case C.EventCode.D:
Log.d("EventBus", "接收到D类型的Event,携带News");
News news = (News) event.getData();
break;
}
}复制代码
在receiveEvent(Event event)
根据对应的事件的code
,判断通讯的数据来源和传递的数据类型,以完成对应的逻辑。
在InfoActivity
中发送事件,InfoActivity
只发送不须要接收Event
的话就不注册,也不用复写isRegisterEventBus()
和receiveEvent(Event event)
方法了。
public void sendEventA(View view) {
EventBusUtil.sendEvent(new Event(C.EventCode.A));
}
public void sendEventB(View view) {
EventBusUtil.sendEvent(new Event(C.EventCode.B));
}
public void sendEventC(View view) {
Event<User> event = new Event<>(C.EventCode.C, new User());
EventBusUtil.sendEvent(event);
}
public void sendEventD(View view) {
Event<News> event = new Event<>(C.EventCode.D, new News());
EventBusUtil.sendEvent(event);
}复制代码
经过上面的方式,将EventBus
封装到BaseActivity/BaseFragment
中,使得EventBus和项目解耦更加完全,同时在须要使用的子Activity/Fragment中只须要复写isRegisterEventBus()
和receiveEvent(Event event)
便可,不用每一个地方都去订阅和取消订阅。而且给Event
给定code
和泛型可以很好的区分不一样的事件来源和数据类型。