EventBus是一款針對Android優(yōu)化的發(fā)布/訂閱事件總線抚恒。可以替代廣播蛤奢、startActivityForResult
、Handler
陶贼、異步回調(diào)等來實現(xiàn)各組件間啤贩、組件與后臺線程間的通信。它的優(yōu)點是開銷小拜秧,代碼更優(yōu)雅痹屹,以及將發(fā)送者和接收者解耦。
通常我們在使用EventBus
的時候都是直接需要接收通信的Activity/Fragment
中通過EventBus.getDefault().register(this)
訂閱事件枉氮,在需要發(fā)起通信的邏輯直接調(diào)用EventBus.getDefault().post(Object event)
來發(fā)布事件志衍。但是要是一個項目中有很多地方都使用EventBus
來通信暖庄,比如重新登錄后更新各個頁面的登錄狀態(tài),或者是接收到通知更新消息提示等楼肪,都這樣直接使用的話代碼重復(fù)率很高培廓,并且呢,如果以后升級或者更換EventBus
時春叫,各個地方都要修改医舆,這就比較麻煩了。因此我一般是將EventBus
的發(fā)布和訂閱封裝到BaseActivity/BaseFragment
中象缀。
在Gradle中添加EventBus
依賴:
compile 'org.greenrobot:eventbus:3.0.0'
封裝一下EventBus
的訂閱、取消訂閱爷速、發(fā)布等方法:
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
如果需要訂閱的話復(fù)寫這個方法并返回true
即可。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (isRegisterEventBus()) {
EventBusUtil.register(this);
}
}
/**
* 是否注冊事件分發(fā)
*
* @return true綁定EventBus事件分發(fā)廉沮,默認不綁定颓遏,子類需要綁定的話復(fù)寫此方法返回true.
*/
protected boolean isRegisterEventBus() {
return false;
}
@Override
public void onDestroy() {
super.onDestroy();
if (isRegisterEventBus()) {
EventBusUtil.unregister(this);
}
}
定義事件Event
:
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>
指定事件通信過程中的數(shù)據(jù)類型,code
為事件碼滞时,使用的時候給不同的事件類型指定不同的code
叁幢。
在BaseActivity\BaseFragment
中添加接收到EventBus
的方法:
/**
* 是否注冊事件分發(fā)
*
* @return true綁定EventBus事件分發(fā),默認不綁定坪稽,子類需要綁定的話復(fù)寫此方法返回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);
}
}
/**
* 接收到分發(fā)到事件
*
* @param event 事件
*/
protected void receiveEvent(Event event) {
}
/**
* 接受到分發(fā)的粘性事件
*
* @param event 粘性事件
*/
protected void receiveStickyEvent(Event event) {
}
根據(jù)自己項目的需求曼玩,在訂閱了EventBus
的Activity/Fragment
中復(fù)寫receiveEvent(Event event)
或receiveStickyEvent(Event event)
來處理接收到事件后的邏輯。
這里也可以不用在BaseActivty/BaseFragment
中添加接受事件的方法(因為添加了過后不能確定的子類的Event
泛型)窒百。那么就直接在訂閱的Activity/Fragment
中給接收事件的方法添加EventBus
對應(yīng)的事件接受注解黍判,并指定參數(shù)Event的泛型。
@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
的地方可以根據(jù)這些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
中復(fù)寫isRegisterEventBus()
并返回true
注冊EventBus
,復(fù)寫receiveEvent(Event event)
接收發(fā)布的事件渤滞。
@Override
protected boolean isRegisterEventBus() {
return true;
}
@Override
protected void receiveEvent(Event event) {
// 接受到Event后的相關(guān)邏輯
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)
根據(jù)對應(yīng)的事件的code
蔼水,判斷通信的數(shù)據(jù)來源和傳遞的數(shù)據(jù)類型震糖,以完成對應(yīng)的邏輯。
在InfoActivity
中發(fā)送事件趴腋,InfoActivity
只發(fā)送不需要接收Event
的話就不注冊吊说,也不用復(fù)寫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中只需要復(fù)寫isRegisterEventBus()
和receiveEvent(Event event)
即可,不用每個地方都去訂閱和取消訂閱雅宾。并且給Event
給定code
和泛型能夠很好的區(qū)分不同的事件來源和數(shù)據(jù)類型养涮。