前言
在平时的开发中,我们常常碰到这样的需求,比如说,我们需要在一个 Activity 中改变另一个 Activity 中的数据。这个需求一般可以用接口或者用广播的形式来实现,但是实现起来步骤较多,比较麻烦。于是就出现了事件总线框架 EventbBus ,很好的解决了问题,用起来也很方便。
不过随着技术的更新,现在很多的开发都用起了 RxJava,同样是基于订阅者模式的 RxJava 是否也可以实现事件总线呢,答案是可以的,如果我们原来的项目用到了 RxJava,现在又有事件总线的需求,就可以考虑使用 RxJava 来实现,这样项目就可以少一个 EventBus 的依赖,减小项目的体积,一举两得。
下面介绍一下如何来搭建一个基于 RxJava 的事件总线。
实现
public class RxBus {
private final Relay
直接上代码,没错,就这么几行代码,就可以实现事件总线,要注意的是,这个类中的百分之70的代码是用来实现事件总线的单例,真正相关的方法只有 post(Object o) 和 toObservable(Class
重点介绍一下 RxBus 里 Relay 类型的变量 mBus 和 post(Object o) 、 toObservable(Class
看一下 Relay 类型的源码介绍。
/**
* Represents a Consumer and an Observable at the same time, allowing
* multicasting events from a single source to multiple child Observers.
* All methods except {@link #accept} are thread-safe.
* Use {@link #toSerialized()} to make it thread-safe as well.
*
* @param the item value type
*/
public abstract class Relay extends Observable implements Consumer {
/** {@inheritDoc} */
意思就是,Relay 类型的对象,既是订阅者又是被订阅者,可以将事件从单一的源头发送给多个订阅者,利用这个特性,就可以用它来实现事件总线。可以看到在方法 post(Object o) 中。
public void post(Object o){
mBus.accept(o);
}
我们调用了他的 accept() 方法,这个 accept() 就类似于我们之前在使用 RxJava 时的 onNext() 方法,通知下游的订阅者进行相应的处理操作。而 toObservable(Class
public Observable toObservable(Class eventType){
return mBus.ofType(eventType);
}
我们可以看到,他的返回类型是 Observable 类型,我们就可以利用他返回的对象,进行订阅的操作。有张图很形象。
图中的 PublishSubject 和 Relay 差不多,由于 RxJava 的特性,当事件触发 onError 或者是 onComplete 的时候,订阅关系就会终止,而在 RxBus 中,我们希望这个订阅关系能一直保持下去,不然一个事件出现问题后,其他的事件就无法处理,而 Relay 正是为了解决这个问题才被设计出来的,所以在 RxBus 中我们用 Relay 而不是 Subject。事件一个个被 post 到这个 Relay 对象上,然后再交由订阅者处理。
原理可能有点绕,直接展示如何使用可能会更好理解。
使用
我们实现一下文章开头所讲的需求,在一个 Activity 中,改变另一个 Activity 中的数据。
第一个界面中有一个跳转至第二个界面的按钮,和一个展示数据的 TextView,第二个界面中有两个按钮,一个是向第一个界面发送消息一,一个是向第一个界面发送消息二。
首先创建需要传输的数据的两个类型,这里我定义了两个类。
public class EventOne {
String msg;
public EventOne(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
public class EventTwo {
String msg;
public EventTwo(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
在第二个界面中发送消息。
@OnClick({R.id.button2, R.id.button3})
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.button2:
RxBus.getInstance().post(new EventOne("消息类型一"));
break;
case R.id.button3:
RxBus.getInstance().post(new EventTwo("消息类型二"));
break;
}
}
在第一个界面中订阅事件。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx1);
ButterKnife.bind(this);
//订阅消息类型一的事件
RxBus.getInstance().toObservable(EventOne.class)
.subscribe(new Consumer() {
@Override
public void accept(EventOne eventOne) throws Exception {
mTextView.setText("已接收" + eventOne.getMsg());
}
});
//订阅消息类型二的事件
RxBus.getInstance().toObservable(EventTwo.class)
.subscribe(new Consumer() {
@Override
public void accept(EventTwo eventTwo) throws Exception {
mTextView.setText("已接收" + eventTwo.getMsg());
}
});
}
在第二个界面中分别点击发送消息后,第一个界面中的效果。
可以看到第一个界面分别对两个事件作出了反应。我们通过第二个 Activity
对第一个 Activity 中的数据进行了修改。RxBus 和 EventBus 的用法差不多,也就是创建要传递的事件类,在一个地方发送消息,在另一个地方接收处理消息。如果要传递不同的事件,就创建不同的事件类,用起来还是很方便的。
最后
RxBus 和 EventBus 为我们提供了事件总线的方式,将一些操作进行了解耦,方便了我们的操作,适当的使用可以提高我们的编程效率,让我们可以把重点放在业务上而不是它的实现上,说白了就是程序员喜欢偷懒,哈哈。
关于 RxBus 和 EventBus 两者之间的选择,那就仁者见仁智者见智了,如果项目里有用到 RxJava 就可以考虑用一下 RxBus, 如果要用 EventBus 也是可以的,我看了一下 EventBus 的包,其实也不大。
(这篇文章昨天晚上没写完,今天早上在地铁上用手机码完了剩下的部分,等下到公司还要去改需求,又是丧丧的一天了( ¨̮ )
以上就是对 RxBus 的介绍:)