一、前言
eventbus3.0的優缺點分析:
eventbus基於觀察者模式,用很少的代碼,幫我們實現很多功能,使我們的代碼變得很優雅。但是大面積的使用eventbus之後,會發現一些很嚴重的問題
- 需要創建很多的類來區分訂閱方法,訂閱的方法越多,類越多,代碼越多,apk的體積越大
- 以類來貫穿這個事件傳遞的方式,廣播方式發送問題後,排查事件源或訂閱方法的難度比較大
- 需要寫很多的訂閱方法,訂閱方法滿天飛,很容易發生dex方法數超出
- 發送的廣播無法收到返回值
- 不知道private的訂閱方法,不知道eventbus爲什麼要這麼設計
- 明明不用發送數據,只是通知,也需要傳遞一個類
- 無法取消單獨的某一個訂閱的方法
圍繞這個上面幾個問題,我在eventbus的基礎上進行了改善。
二、改善說明: 基於android eventbus 3.0 版本優化:
-
優化前期以類爲區分監聽接收對象,需要創建很多類,優化後採用字符串方式作爲事件event-key區分代替以類的方式,避免創建太多類,減少代碼量,比較優雅,本思想也參考ios通知的實現。
-
支持返回值,支持private和static的方法
-
優化前,訂閱者需要訂閱很多監聽方法來區分分類,優化後可以減少監聽方法,在一個方法或多個方法裏面進行分類判斷即可,思想來自handler
-
優化前維護難,表現在不清楚事件發生源,優化後,可以統一管理事件vent key,方便管理查找bug
-
支持只發送事件的功能
-
支持冷凍事件方法,和解除冷凍事件的方法
其他方面如Subscribe訂閱方法,線程模式的,粘性事件等的處理均和eventbus3.0的處理一致。
項目使用:
androidstudio gradle 引入:implementation ‘com.github.chenjk-520:keventbus:1.1’
項目開源地址:github地址
,如果覺得好用就給個Star或給個打賞吧。如果需要改進的地方,清在下面評論或發送私信到我的郵件[email protected]
三、使用說明
和eventbus3.0版本的使用方式差不多,是eventbus3.0改進,下面看看怎麼使用
- 瞭解使用之前先了解一下其中一個關鍵的類EventMessage
private T msg;
private String event;
private int arg;
private CallBack callBack;
msg是我們需要發送的數據,可以是任何數據
event是我們一個事件對應的event,通過這個event我們可以找到訂閱的方法。
arg,是event的在一次分類
callBack 是處理髮送廣播後的回調。
1.註冊事件與取消註冊事件
註冊事件:
KeventBus.getDefault().register(this);
取消註冊事件:
KeventBus.getDefault().unregister(this);
2. 只使用event-key,不發送數據
發送事件:
KeventBus.getDefault().post(TestKey.SAY_HELLO);
接收事件:
@Subscribe(event = TestKey.SAY_HELLO,threadMode = ThreadMode.MAIN)
public void hello(EventMessage<String> msg){
Log.i("TAG",msg.getEvent());
}
其中post事件TestKey.SAY_HELLO,與@Subscribe的event = TestKey.SAY_HELLO一一對應纔可以接收到
3. 使用event-key,併發送數據
發送事件:
KeventBus.getDefault().post(new EventMessage<>("say hello!",TestKey.SAY_HELLO));
這裏的構造函數參數分別是msg,event
接收數據:
@Subscribe(event = TestKey.SAY_HELLO,threadMode = ThreadMode.MAIN)
public void hello(EventMessage<String> msg){
Log.i("TAG",msg.getMsg());
}
4. 使用event-key,併發送數據, 在同一訂閱方法裏面再區分,有點類似handler的message,event相當於是what屬性,arg也跟message的arg一樣
發送事件1:
KeventBus.getDefault().post(new EventMessage("data==1",TestKey.SAY_HELLO,1));
發送事件2:
KeventBus.getDefault().post(new EventMessage("data==2",TestKey.SAY_HELLO,2));
這裏的構造函數參數分別是msg,event,arg
接收事件:
@Subscribe(event = TestKey.SAY_HELLO,threadMode = ThreadMode.MAIN)
public void hello34(EventMessage<String> msg){
if (msg.getArg() == 1){
Toast.makeText(this,msg.getMsg(),Toast.LENGTH_SHORT).show();
}else if(msg.getArg() == 2 ){
Toast.makeText(this,msg.getMsg(),Toast.LENGTH_SHORT).show();
}
}
5. 支持發送訂閱消息後回調
發送訂閱消息:
KeventBus.getDefault().post(new EventMessage<String>("測試data",TestKey.SAY_HELLO, new EventMessage.CallBack<String>() {
@Override
public void onCall(String result, int arg) {
//在這裏處理回調數據
Log.i("TAG",result);
}
}));
接收事件:
@Subscribe(event = TestKey.SAY_HELLO4,threadMode = ThreadMode.ASYNC,enback = true)
private String hello5(EventMessage msg){
Log.i("TAG",msg.getMsg());
return "測試返回值";
}
注意:
1.接收事件需要加上enback = true
2.這裏的回調之後的是接收事件的線程,如果在主線程裏面發出的,在子線程接收並返回的事件,回調的方法是接收方法的線程,如果需要toast的話,需要自己切換到主線程再處理
5. 支持冷凍事件和激活事件
說明: 冷凍事件後,發送相對應的事件,訂閱的方法將不能接收到這個時間,但這個訂閱的方法並沒有真的移除掉,可以通過重新激活這個方法,下次發送便可以再接收到
冷凍方法:
KeventBus.getDefault().freezeSubscribeEvent(TestKey.SAY_HELLO);
激活方法:
KeventBus.getDefault().activeEvent(TestKey.SAY_HELLO);