前言
在网上看了很多实现,基本就是一个套路。用RxJava来实现事件总线并不复杂,简单几行代码就可以完成。但是那些文章都说的太简单了,基本就是教你简单实现过后怎么用就完事。有些细节还是有必要说清楚的,不然其实看不太明白。所以本文的主要目的不是实现,而是把实现的一些细节清楚的讲出来。弥补那些千篇一律的文章的不足。(ps:我假设你RxJava已入门哦,未入门的童鞋可参考我的上一篇文章或者学习其他大牛的杰作)
正文
先把大家都认同的实现代码贴出来
public class RxBus {
private Subject bus;
RxBus() {
bus = new SerializedSubject(PublishSubject.create());
}
private static class BusSingleHolder {
private static final RxBus Instance = new RxBus();
}
//单例模式
public static RxBus getInstance() {
return BusSingleHolder.Instance;
}
/**
* 发送消息 即调用所有观察者的onNext()方法
* @param obj
*/
public void send(Object obj) {
bus.onNext(obj);//这里调用的是所有存在的observaber的onNext()方法
}
public <T> Observable<T> getObservable(Class<T> eventType) {
return bus.ofType(eventType);//filter(..).cast(..) 包含过滤和转换类型两个动作,只发送出指定类型的消息
}
}
使用:
//发送方
RxBus.getInstance().send("发了条消息");
//接收方
Subscription subscription = RxBus.getInstance().getObservable(String.class)
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError" + e.getMessage());
}
@Override
public void onNext(String s) {
Log.d(TAG, "receive: " + s);
}
});
//解绑
subscription.unsubscribe();
可以看到,代码非常少,乍一浏览完,你可能会有些疑惑,比如Subject 这个类,比如详细的发送和接收流程……先不急着看这个,一步一步来,我们去掉一些枝叶,把主干提取出来。
Subject subject = PublishSubject.create();
subject.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.d(TAG,"receive: "+o.toString());
}
});
subject.onNext("send something");
看到了吧,实际上最主干的一个东西就是Subject 的一个实例,把它设置成全局变量过后,可发可收。看看这个类;
public abstract class Subject<T, R> extends Observable<R> implements Observer<T>
它继承了Observable也实现了Observer接口,所以它既是发布者,也是订阅者并且是一个抽象类,这里用它的子类PublishSubject(为啥用它先暂时不管,下面再说),再来看它的发送的方法:
// final SubjectSubscriptionManager<T> state = new SubjectSubscriptionManager<T>();
//state 是一个订阅者的管理类
@Override
public void onNext(T v) {
for (SubjectObserver<T> bo : state.observers()) {
bo.onNext(v);
}
}
所以,发送的方法其实就是调用所有观察者的onNext()方法开始执行。这点知道观察者模式的同学应该都了解。那么,怎么添加订阅者呢,subject.subscribe()方法嘛!它自己同时充当两种角色,既发送,又接收嘛。所以这时候来按正确的顺序捋一捋这个流程:
1.创建全局的可发送可接收消息的Subject实例
2.通过subject.subscribe()给自己添加订阅者(subscriber/observaber)
3.通过subject.onNext()调用所有订阅者的执行方法,即所谓的”发送消息”。
至此,主干流程梳理完毕。是否清晰一些了?
我们再回到原来的代码中,发送的方法不用再解释了。这里还有一个getObservable方法,调用subject.ofType()方法,源码如下:
public final <R> Observable<R> ofType(final Class<R> klass) {
return filter(InternalObservableUtils.isInstanceOf(klass)).cast(klass);
}
ofType()其实就是根据传入对象的类型进行过滤和转换操作之后返回只发射指定类型Observable的方法。简单说,获取发射指定类型数据的发布者。获取了发布者就可以添加指定数据类型的订阅者。这样方便在发送数据的时候根据数据类型来区分哪些订阅者来接收消息,分类发送,避免混乱。
然后还有一个PublishSubject类,只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。如果在订阅之前就发送,没有接收者接收,没有意义。在事件总线的处理上,它算是比较适合的一个Subject子类吧。
再有,关于SerializedSubject,Subject是线程非安全的,要避免这个问题,所以给转换为SerializedSubject。
总结
到这里,主干和枝叶都讲完了。最后一起再来梳理一把:
1.创建一个线程安全的全局静态的PublishSubject,既充当发布者、又充当订阅者。
2.通过ofType()方法获取指定了数据类型的发布者角色(Observable),通过它的subscribe()方法添加订阅者(同样指定了数据类型)。
3.通过onNext()方法,调用所有所有符合数据类型的订阅者的onNext()方法。完成”数据的发送”;
所有的流程大致就是这样了。有没有更清楚一些?
欢迎拍砖,欢迎指正哦!谢谢!