Android RxJava 实现RxBus

来源:互联网 发布:大智慧大数据终端破解 编辑:程序博客网 时间:2024/05/16 17:23

前言


以前在项目中使用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》

0 0