前言:
上篇文章學習了Android事件匯流排管理開源框架EventBus,EventBus的出現大大降低了開發成本以及開發難度,今天我們就利用目前大紅大紫的RxJava來實現一下類似EventBus事件匯流排管理,現在很多人都在說用這種方式來替代EventBus,今天我們從開發效率,開發難度等維度來分析一下到底能不能取代EventBus? 先回顧一下什麼是EventBus?請看這篇文章Android訊息傳遞之EventBus 3.0使用詳解(三)
訊息傳遞相關文章地址:
- Android訊息傳遞之Handler訊息機制
- Android訊息傳遞之元件間傳遞訊息
- Android訊息傳遞之EventBus 3.0使用詳解
- Android訊息傳遞之基於RxJava實現一個EventBus - RxBus
需求:
雖然軟體工程師就害怕聽見“需求”這兩個字,但是一切功能來源於需求,我們要基於RxJava實現一個publish/subscribe訊息匯流排管理模型,這裡假設你已經知道如何使用RxJava了。下面看看如何實現。
RxBus實現過程:
1.)build.gradle中新增RxJava、RxAndroid引用
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.2'
2.)宣告一個管理事件匯流排的單例
public class RxBus { private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>(); private static volatile RxBus instance; private RxBus() { } public static RxBus getInstance() { RxBus inst = instance; if (inst == null) { synchronized (RxBus.class) { inst = instance; if (inst == null) { inst = new RxBus(); instance = inst; } } } return inst; } }
考慮到RxBus單例很有可能多執行緒併發訪問,這種儲存事件匯流排採用ConcurrentHashMap
3.)訂閱者實現註冊/解除註冊方法
註冊/解註冊都以一個tag為唯一標示,這裡採用的是事件的Class為tag,來實現一個Event事件物件可以對應多個訂閱者。
/** * 註冊 * * @param tag * @return */ public <T> Observable<T> register(@NonNull Class<T> tag) { List<Subject> subjectList = subjectMapper.get(tag); if (null == subjectList) { subjectList = new ArrayList<>(); subjectMapper.put(tag, subjectList); } Subject<T, T> subject = PublishSubject.create(); subjectList.add(subject); return subject; } /** * 解除註冊 * * @param tag */ public <T> void unregister(@NonNull Class<T> tag, @NonNull Observable observable) { List<Subject> subjects = subjectMapper.get(tag); if (null != subjects) { subjects.remove(observable); if (subjects.isEmpty()) { subjectMapper.remove(tag); } } }
4.)實現傳送訊息、清除所有註冊
傳送一個事件訊息是通過獲取當前事件下的訂閱者列表,然後通過一個迴圈進行事件傳遞。至於事件執行在哪個執行緒中由訂閱者決定。
/** * 傳送訊息 * * @param event */ public <T> void post(@NonNull Object event) { List<Subject> subjectList = subjectMapper.get(event.getClass()); if (subjectList != null && !subjectList.isEmpty()) { for (Subject subject : subjectList) { subject.onNext(event); } } } /** * 清除訂閱 */ public void clear() { if (subjectMapper.isEmpty()) { return; } subjectMapper.clear(); }
5.)如何使用
事件的訂閱者的註冊和清除所有註冊,訂閱者沒訂閱一個型別的事件都要返回一個Observable物件,這也是個人覺得比較頭疼的一件事,很難實現一個訂閱者對應多個事件型別,而且解註冊的時候也需要這些Observable物件進行一一解除。
private Observable<DataSynEvent> observable; private void registerObservable() { observable = RxBus.getInstance().register(DataSynEvent.class); observable.observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<DataSynEvent>() { @Override public void call(DataSynEvent event) { Log.e(TAG, "event--2-->" + event.getCount()); } }); } private void unRegisterObservable() { if (observable != null) { RxBus.getInstance().unregister(DataSynEvent.class, observable); } }
事件的傳送者傳送事件,傳送事件的處理還算比較友好,和EventBus很類似。
RxBus.getInstance().post(new DataSynEvent());
RxBus、EventBus 對比:
1.從引入依賴包對比
RxBus 需要引入兩個包,EventBus需要引入一個,如果專案中沒有使用到RxJava程式設計的話,並不能減少包的依賴。
2 .從開發難度上對比
上面也提到了實現RxBus是基於RxJava的,作為一個新的程式設計方式函數語言程式設計,對開發者的要求多多少少提高了那麼一點,而且每一個訂閱都需要返回一個Observable,由訂閱者寫具體的程式碼 需要執行在哪個執行緒中,而EventBus 最新版本採用註解預編譯的方式,訂閱者註冊解註冊只需呼叫一個函式,而且通過註解的方式可以標明事件的優先順序,接收事件執行在哪個執行緒,並且能夠實現粘性事件,這些RxBus都需要進行二次開發。
3.)從開發效率上對比
RxBus 需要進行大量的二次開發,否則只能實現簡單的事件傳遞,而EventBus只需簡單瞭解一下API就能上手。如果一個訂閱者需要註冊多個事件的時候,需要多個Observable全域性變數,這不是瘋掉了嗎,而EventBus已經實現了一個訂閱者訂閱多個事件,和一個事件對應多個訂閱者。
4.)從功能完善上對比
上面三個對比也說明了,EventBus實現了事件的優先順序,訂閱事件執行的執行緒場景,以及粘性事件,這些在RxBus上面都需要進行二次實現。
總結:
基於RxJava實現簡單的事件匯流排管理是可以的,但是個人覺得想要取代EventBus難免有點說過頭了。所以如果專案中沒有使用RxJava的話 還是採用EventBus比較靠譜。