RxBus—使用RxJava实现的EventBus

前言

  在平时的开发中,我们常常碰到这样的需求,比如说,我们需要在一个 Activity 中改变另一个 Activity 中的数据。这个需求一般可以用接口或者用广播的形式来实现,但是实现起来步骤较多,比较麻烦。于是就出现了事件总线框架 EventbBus ,很好的解决了问题,用起来也很方便。
  不过随着技术的更新,现在很多的开发都用起了 RxJava,同样是基于订阅者模式的 RxJava 是否也可以实现事件总线呢,答案是可以的,如果我们原来的项目用到了 RxJava,现在又有事件总线的需求,就可以考虑使用 RxJava 来实现,这样项目就可以少一个 EventBus 的依赖,减小项目的体积,一举两得。
  下面介绍一下如何来搭建一个基于 RxJava 的事件总线。

实现

public class RxBus {
    private final Relay<Object> mBus;

    private RxBus() {
        mBus = PublishRelay.create().toSerialized();
    }

    public static RxBus getInstance(){
        return InstanceHolder.INSTANCE;
    }

    private static class InstanceHolder{
        private static final RxBus INSTANCE = new RxBus();
    }

    public void post(Object o){
        mBus.accept(o);
    }

    public <T> Observable<T> toObservable(Class<T> eventType){
        return mBus.ofType(eventType);
    }
}

  直接上代码,没错,就这么几行代码,就可以实现事件总线,要注意的是,这个类中的百分之70的代码是用来实现事件总线的单例,真正相关的方法只有 post(Object o) 和 toObservable(Class<T> eventType) 两个。RxBus 并不是一个框架,而是一种使用 RxJava 实现事件总线的一种解决思路,实质是交由 RxJava 去实现。
  重点介绍一下 RxBus 里 Relay 类型的变量 mBus 和 post(Object o) 、 toObservable(Class<T> eventType) 两个方法(好像就这三个需要介绍,哈哈)。
  看一下 Relay 类型的源码介绍。

/**
 * Represents a Consumer and an Observable at the same time, allowing
 * multicasting events from a single source to multiple child Observers.
 * <p>All methods except {@link #accept} are thread-safe.
 * Use {@link #toSerialized()} to make it thread-safe as well.
 *
 * @param <T> the item value type
 */
public abstract class Relay<T> extends Observable<T> implements Consumer<T> {
    /** {@inheritDoc} */

  意思就是,Relay 类型的对象,既是订阅者又是被订阅者,可以将事件从单一的源头发送给多个订阅者,利用这个特性,就可以用它来实现事件总线。可以看到在方法 post(Object o) 中。

    public void post(Object o){
        mBus.accept(o);
    }

  我们调用了他的 accept() 方法,这个 accept() 就类似于我们之前在使用 RxJava 时的 onNext() 方法,通知下游的订阅者进行相应的处理操作。而 toObservable(Class<T> eventType) 方法。

    public <T> Observable<T> toObservable(Class<T> 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<EventOne>() {
                    @Override
                    public void accept(EventOne eventOne) throws Exception {
                        mTextView.setText("已接收" + eventOne.getMsg());
                    }
                });
        
        //订阅消息类型二的事件
        RxBus.getInstance().toObservable(EventTwo.class)
                .subscribe(new Consumer<EventTwo>() {
                    @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 的介绍:)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,077评论 25 707
  • 对于Android系统来说,消息传递是最基本的组件,每一个App内的不同页面,不同组件都在进行消息传递。消息传递既...
    bondPang阅读 2,033评论 6 32
  • EventBus是什么 EventBus是为Android优化的发布/订阅事件总线 [图片上传失败...(imag...
    小甜李子阅读 1,155评论 1 1
  • 喜欢明了的心境,清楚的感觉和简单的事物。想的透彻才能活的通透。很喜欢和三观超正的人相处,这些人想法都普遍大胆且有趣...
    阿珂小姐姐呀阅读 335评论 1 1
  • 在武汉的十年,2013年8月18日是最丰富的一天,这得感谢赵女士。赵女士是一个很特别的女人,也是一个很特别的武汉边...
    唠唠叨叨的Ali阅读 314评论 0 0