Android RxJava 实现 RxBus

3,790 阅读3分钟
原文链接: blog.csdn.net

前言


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

参考


www.cnblogs.com/tiantianbyc… 《[Android]基于RxJava、RxAndroid的EventBus实现》
johnnyshieh.github.io/android/201… 《RxJava 2 版本的 Rxbus》