RxBus—使用RxJava實(shí)現(xiàn)的EventBus

前言

??在平時(shí)的開(kāi)發(fā)中,我們常常碰到這樣的需求,比如說(shuō),我們需要在一個(gè) Activity 中改變另一個(gè) Activity 中的數(shù)據(jù)。這個(gè)需求一般可以用接口或者用廣播的形式來(lái)實(shí)現(xiàn),但是實(shí)現(xiàn)起來(lái)步驟較多,比較麻煩。于是就出現(xiàn)了事件總線(xiàn)框架 EventbBus ,很好的解決了問(wèn)題,用起來(lái)也很方便。
??不過(guò)隨著技術(shù)的更新,現(xiàn)在很多的開(kāi)發(fā)都用起了 RxJava,同樣是基于訂閱者模式的 RxJava 是否也可以實(shí)現(xiàn)事件總線(xiàn)呢,答案是可以的,如果我們?cè)瓉?lái)的項(xiàng)目用到了 RxJava,現(xiàn)在又有事件總線(xiàn)的需求,就可以考慮使用 RxJava 來(lái)實(shí)現(xiàn),這樣項(xiàng)目就可以少一個(gè) EventBus 的依賴(lài),減小項(xiàng)目的體積,一舉兩得。
??下面介紹一下如何來(lái)搭建一個(gè)基于 RxJava 的事件總線(xiàn)。

實(shí)現(xiàn)

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);
    }
}

??直接上代碼,沒(méi)錯(cuò),就這么幾行代碼,就可以實(shí)現(xiàn)事件總線(xiàn),要注意的是,這個(gè)類(lèi)中的百分之70的代碼是用來(lái)實(shí)現(xiàn)事件總線(xiàn)的單例,真正相關(guān)的方法只有 post(Object o) 和 toObservable(Class<T> eventType) 兩個(gè)。RxBus 并不是一個(gè)框架,而是一種使用 RxJava 實(shí)現(xiàn)事件總線(xiàn)的一種解決思路,實(shí)質(zhì)是交由 RxJava 去實(shí)現(xiàn)。
??重點(diǎn)介紹一下 RxBus 里 Relay 類(lèi)型的變量 mBus 和 post(Object o) 、 toObservable(Class<T> eventType) 兩個(gè)方法(好像就這三個(gè)需要介紹,哈哈)。
??看一下 Relay 類(lèi)型的源碼介紹。

/**
 * 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 類(lèi)型的對(duì)象,既是訂閱者又是被訂閱者,可以將事件從單一的源頭發(fā)送給多個(gè)訂閱者,利用這個(gè)特性,就可以用它來(lái)實(shí)現(xiàn)事件總線(xiàn)??梢钥吹皆诜椒?post(Object o) 中。

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

??我們調(diào)用了他的 accept() 方法,這個(gè) accept() 就類(lèi)似于我們之前在使用 RxJava 時(shí)的 onNext() 方法,通知下游的訂閱者進(jìn)行相應(yīng)的處理操作。而 toObservable(Class<T> eventType) 方法。

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

??我們可以看到,他的返回類(lèi)型是 Observable 類(lèi)型,我們就可以利用他返回的對(duì)象,進(jìn)行訂閱的操作。有張圖很形象。



??圖中的 PublishSubject 和 Relay 差不多,由于 RxJava 的特性,當(dāng)事件觸發(fā) onError 或者是 onComplete 的時(shí)候,訂閱關(guān)系就會(huì)終止,而在 RxBus 中,我們希望這個(gè)訂閱關(guān)系能一直保持下去,不然一個(gè)事件出現(xiàn)問(wèn)題后,其他的事件就無(wú)法處理,而 Relay 正是為了解決這個(gè)問(wèn)題才被設(shè)計(jì)出來(lái)的,所以在 RxBus 中我們用 Relay 而不是 Subject。事件一個(gè)個(gè)被 post 到這個(gè) Relay 對(duì)象上,然后再交由訂閱者處理。
??原理可能有點(diǎn)繞,直接展示如何使用可能會(huì)更好理解。

使用

??我們實(shí)現(xiàn)一下文章開(kāi)頭所講的需求,在一個(gè) Activity 中,改變另一個(gè) Activity 中的數(shù)據(jù)。
??第一個(gè)界面中有一個(gè)跳轉(zhuǎn)至第二個(gè)界面的按鈕,和一個(gè)展示數(shù)據(jù)的 TextView,第二個(gè)界面中有兩個(gè)按鈕,一個(gè)是向第一個(gè)界面發(fā)送消息一,一個(gè)是向第一個(gè)界面發(fā)送消息二。


第一個(gè)界面
第二個(gè)界面

??首先創(chuàng)建需要傳輸?shù)臄?shù)據(jù)的兩個(gè)類(lèi)型,這里我定義了兩個(gè)類(lèi)。

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;
    }
}

??在第二個(gè)界面中發(fā)送消息。

    @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("消息類(lèi)型一"));
                break;
            case R.id.button3:
                RxBus.getInstance().post(new EventTwo("消息類(lèi)型二"));
                break;
        }
    }

??在第一個(gè)界面中訂閱事件。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rx1);
        ButterKnife.bind(this);
         
        //訂閱消息類(lèi)型一的事件
        RxBus.getInstance().toObservable(EventOne.class)
                .subscribe(new Consumer<EventOne>() {
                    @Override
                    public void accept(EventOne eventOne) throws Exception {
                        mTextView.setText("已接收" + eventOne.getMsg());
                    }
                });
        
        //訂閱消息類(lèi)型二的事件
        RxBus.getInstance().toObservable(EventTwo.class)
                .subscribe(new Consumer<EventTwo>() {
                    @Override
                    public void accept(EventTwo eventTwo) throws Exception {
                        mTextView.setText("已接收" + eventTwo.getMsg());
                    }
                });
    }

??在第二個(gè)界面中分別點(diǎn)擊發(fā)送消息后,第一個(gè)界面中的效果。


事件一
事件二

??可以看到第一個(gè)界面分別對(duì)兩個(gè)事件作出了反應(yīng)。我們通過(guò)第二個(gè) Activity
對(duì)第一個(gè) Activity 中的數(shù)據(jù)進(jìn)行了修改。RxBus 和 EventBus 的用法差不多,也就是創(chuàng)建要傳遞的事件類(lèi),在一個(gè)地方發(fā)送消息,在另一個(gè)地方接收處理消息。如果要傳遞不同的事件,就創(chuàng)建不同的事件類(lèi),用起來(lái)還是很方便的。

最后

??RxBus 和 EventBus 為我們提供了事件總線(xiàn)的方式,將一些操作進(jìn)行了解耦,方便了我們的操作,適當(dāng)?shù)氖褂每梢蕴岣呶覀兊木幊绦剩屛覀兛梢园阎攸c(diǎn)放在業(yè)務(wù)上而不是它的實(shí)現(xiàn)上,說(shuō)白了就是程序員喜歡偷懶,哈哈。
??關(guān)于 RxBus 和 EventBus 兩者之間的選擇,那就仁者見(jiàn)仁智者見(jiàn)智了,如果項(xiàng)目里有用到 RxJava 就可以考慮用一下 RxBus, 如果要用 EventBus 也是可以的,我看了一下 EventBus 的包,其實(shí)也不大。
??(這篇文章昨天晚上沒(méi)寫(xiě)完,今天早上在地鐵上用手機(jī)碼完了剩下的部分,等下到公司還要去改需求,又是喪喪的一天了( ¨? )

以上就是對(duì) RxBus 的介紹:)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,812評(píng)論 25 709
  • 對(duì)于Android系統(tǒng)來(lái)說(shuō),消息傳遞是最基本的組件,每一個(gè)App內(nèi)的不同頁(yè)面,不同組件都在進(jìn)行消息傳遞。消息傳遞既...
    bondPang閱讀 2,105評(píng)論 6 32
  • EventBus是什么 EventBus是為Android優(yōu)化的發(fā)布/訂閱事件總線(xiàn) [圖片上傳失敗...(imag...
    小甜李子閱讀 1,193評(píng)論 1 1
  • 喜歡明了的心境,清楚的感覺(jué)和簡(jiǎn)單的事物。想的透徹才能活的通透。很喜歡和三觀超正的人相處,這些人想法都普遍大膽且有趣...
    阿珂小姐姐呀閱讀 396評(píng)論 1 1
  • 在武漢的十年,2013年8月18日是最豐富的一天,這得感謝趙女士。趙女士是一個(gè)很特別的女人,也是一個(gè)很特別的武漢邊...
    嘮嘮叨叨的Ali閱讀 384評(píng)論 0 0

友情鏈接更多精彩內(nèi)容