前言
以前在項目中使用EventBus,來進行事件通知與訂閱。
現在使用RxJava實現一個發布/訂閱事件匯流排:RxBus。 rxjava 1.x實現 RxBus代碼:
/** * desc : 利用 PublishSubject的特性:與普通的Subject不同,在訂閱時並不立即觸發訂閱事件, * 而是允許我們在任意時刻手動調用onNext(),onError(),onCompleted來觸發事件。 * author : stone * email : aa86799@163.com * time : 24/04/2017 11 20 */public class RxBus { private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>(); private RxBus() { } private static class Holder { private static RxBus instance = new RxBus(); } public static RxBus getInstance() { return Holder.instance; } public <T> Observable<T> register(@NonNull Class<T> clz) { return register(clz.getName()); } public <T> Observable<T> register(@NonNull Object 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); //System.out.println("註冊到rxbus"); return subject; } public <T> void unregister(@NonNull Class<T> clz, @NonNull Observable observable) { unregister(clz.getName(), observable); } public void unregister(@NonNull Object tag, @NonNull Observable observable) { List<Subject> subjects = subjectMapper.get(tag); if (null != subjects) { subjects.remove(observable); if (subjects.isEmpty()) { subjectMapper.remove(tag); //System.out.println("從rxbus取消註冊"); } } } public void post(@NonNull Object content) { post(content.getClass().getName(), content); } public void post(@NonNull Object tag, @NonNull Object content) { List<Subject> subjects = subjectMapper.get(tag); if (!subjects.isEmpty()) { for (Subject subject: subjects) { subject.onNext(content); } } }}
幾個關鍵方法:
register —— 由tag,產生一個subject List,同時利用PublishSubject建立一個Subject並返回,它同時也是Observable的子類。
unregister —— 移除tag對應subject List 中的Observable。若subject List為空白,也將被移除。
post —— 遍曆tag對應subject List 中的Subject,執行onNext()。這裡實際執行的是觀察者Observer的onNext(),Subject的定義:public abstract class Subject<T, R> extends Observable<R> implements Observer<T>。 測試代碼:
/*rxbus */Observable<String> observable = RxBus.getInstance().register(String.class);observable.map(s -> { try { int v = Integer.valueOf(s); System.out.println("map變換成功, source = " + s); return v; } catch (Exception e) { System.out.println("map變換失敗, source = " + s); return s; }}).subscribe(value -> { System.out.println("訂閱 " + value);});RxBus.getInstance().post("888");RxBus.getInstance().post("發發發");RxBus.getInstance().unregister(String.class, observable);
這裡比較有意思的是,使用了lambda運算式。在map變換時,如果將字串轉成Integer,沒有問題就返回整型;若報異常,就返回String型。同樣的,在最終訂閱時,value參數的類型也是由map變換來決定的。
rxjava 2.x實現
在 RxJava 2.0 之後,io.reactivex.Observable中沒有進行背壓處理了,如果有大量訊息堆積在匯流排中來不及處理會產生MissingBackpressureException或者OutOfMemoryError,有新的類io.reactivex.Flowable 專門針對背壓問題。
無背壓處理的Observable實現,跟rxjava1.x中一樣,使用PublishSubject來實現。
要實現有背壓的2.x版,使用FlowableProcessor的子類PublishProcessor 來產生 Flowable,以實現 RxBus。 RxBus代碼:
public class RxBus { private final FlowableProcessor<Object> mBus; private RxBus() { mBus = PublishProcessor.create().toSerialized(); } private static class Holder { private static RxBus instance = new RxBus(); } public static RxBus getInstance() { return Holder.instance; } public void post(@NonNull Object obj) { mBus.onNext(obj); } public <T> Flowable<T> register(Class<T> clz) { return mBus.ofType(clz); } public void unregisterAll() { //會將所有由mBus 產生的 Flowable 都置 completed 狀態 後續的 所有訊息 都收不到了 mBus.onComplete(); } public boolean hasSubscribers() { return mBus.hasSubscribers(); }} 測試代碼:
Flowable<Integer> f1 = RxBus.getInstance().register(Integer.class);f1.subscribe(value -> System.out.println("訂閱f1訊息 .. " + value));RxBus.getInstance().post(999);
參考
http://www.cnblogs.com/tiantianbyconan/p/4578699.html 《[Android]基於RxJava、RxAndroid的EventBus實現》
http://johnnyshieh.github.io/android/2017/03/10/rxbus-rxjava2/?utm_source=tuicool&utm_medium=referral 《RxJava 2 版本的 Rxbus》