1. 程式人生 > >基於RxJava2的RxBus,打造屬於你自己的EventBus

基於RxJava2的RxBus,打造屬於你自己的EventBus

前言

由於最近在學RxJava2,同樣避免不了使用Rxbus,但是RxJava1到RxJava2還是有很大的變化的,例如:在 2.x 中 Observable 不支援背壓了,將用一個全新的 Flowable 來支援背壓,Consumer和BiConsumer對Action1 和Action2進行了替換,Function 替換了Func1,採用BiFunction 替換Func 2..N。並且,它們都增加了throws Exception,也就是說,媽媽再也不用擔心我們做某些操作還需要try-catch了。所以我們以前的基於Rxjava1的RxBus就要升級改造下。

RxBus版本一

對於RxJava1.x.x,相信大家都已經用的很熟了,RxBus也不在話下,下面是本人在RxJava1版本使用的RxJava,程式碼裡有很詳細的註釋。這裡就不多說了!

  • RxBus1
public class RxBus {

//    private static volatile RxBus mInstance;
    private SerializedSubject<Object, Object> mSubject;
    private HashMap<String, CompositeSubscription> mSubscriptionMap;

    /**
     *
     * 1、Subject同時充當了Observer和Observable的角色,Subject是非執行緒安全的,要避免該問題,
     * 需要將 Subject轉換為一個 SerializedSubject,類中把執行緒非安全的PublishSubject包裝成執行緒安全的Subject。
     * 2、PublishSubject只會把在訂閱發生的時間點之後來自原始Observable的資料發射給觀察者。
     *
     */
public RxBus() { mSubject = new SerializedSubject<>(PublishSubject.create()); } // 這裡使用Dagger來處理單例 /* private RxBus() { mSubject = new SerializedSubject<>(PublishSubject.create()); } public static RxBus getInstance() { if (mInstance == null) { synchronized (RxBus.class) { if (mInstance == null) { mInstance = new RxBus(); } } } return mInstance; }*/
/** * 傳送事件 * * @param o */ public void post(Object o) { mSubject.onNext(o); } /** * 返回指定型別的Observable例項 * 1、ofType操作符只發射指定型別的資料,其內部就是filter+cast * @param type * @param <T> * @return */ public <T> Observable<T> toObservable(final Class<T> type) { return mSubject.ofType(type); } /** * 是否已有觀察者訂閱 * * @return */ public boolean hasObservers() { return mSubject.hasObservers(); } /** * 一個預設的訂閱方法 * * @param type * @param next * @param error * @param <T> * @return */ public <T> Subscription doSubscribe(Class<T> type, Action1<T> next, Action1<Throwable> error) { return toObservable(type) // 加上背壓處理,不然有些地方會有異常,關於背壓參考這裡:https://gold.xitu.io/post/582d413c8ac24700619cceed .onBackpressureBuffer() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(next, error); } /** * 儲存訂閱後的subscription * @param o * @param subscription */ public void addSubscription(Object o, Subscription subscription) { if (mSubscriptionMap == null) { mSubscriptionMap = new HashMap<>(); } String key = o.getClass().getName(); if (mSubscriptionMap.get(key) != null) { mSubscriptionMap.get(key).add(subscription); } else { // 代表一組訂閱,訂閱 unsubscribed在一起 CompositeSubscription compositeSubscription = new CompositeSubscription(); compositeSubscription.add(subscription); mSubscriptionMap.put(key, compositeSubscription); } } /** * 取消訂閱 * @param o */ public void unSubscribe(Object o) { if (mSubscriptionMap == null) { return; } String key = o.getClass().getName(); if (!mSubscriptionMap.containsKey(key)){ return; } if (mSubscriptionMap.get(key) != null) { mSubscriptionMap.get(key).unsubscribe(); } mSubscriptionMap.remove(key); } }

RxBus版本二

在這之前我們先熟悉下EventBus和RxJava的原理,這裡只是簡單聊聊:
EventBus
EventBus是Android下高效的釋出/訂閱事件匯流排機制,是一種釋出訂閱設計模式(Publish/Subsribe),或稱作觀察者設計模式。
RxJava
RxJava 的非同步實現,是通過一種擴充套件的觀察者模式來實現的。RxJava 有四個基本概念:Observable (可觀察者,即被觀察者)、 Observer (觀察者)、 subscribe (訂閱)、事件。Observable 和 Observer 通過 subscribe() 方法實現訂閱關係,從而 Observable 可以在需要的時候發出事件來通知 Observer。
明白了什麼是觀察者模式,我們才能更好地對RxBbus1改造成我們需要的RxBus2.

  • RxBus2
    翻Rxjava2的文件,我們知道在RxJava2中已經沒了SerializedSubject類,我們可以呼叫toSerialized()方法,對Subject包裝序列化,使其變成執行緒安全的。由於Rxjava2使用Flowable支援背壓,我們可以將其轉換成帶背壓的Flowable例項。基本上bus1和bus2的區別就這些!
public class RxBus {
    private HashMap<String, CompositeDisposable> mSubscriptionMap;
    private static volatile RxBus mRxBus;
    private final Subject<Object> mSubject;
    //單列模式
    public static RxBus getIntanceBus(){
        if (mRxBus==null){
            synchronized (RxBus.class){
                if(mRxBus==null){
                    mRxBus = new RxBus();
                }
            }
        }
        return mRxBus;
    }
    public RxBus(){
         mSubject = PublishSubject.create().toSerialized();
    }

    public void post(Object o){
        mSubject.onNext(o);
    }
    /**
     * 返回指定型別的帶背壓的Flowable例項
     *
     * @param <T>
     * @param type
     * @return
     */
    public <T>Flowable<T> getObservable(Class<T> type){
        return mSubject.toFlowable(BackpressureStrategy.BUFFER)
                .ofType(type);
    }
    /**
     * 一個預設的訂閱方法
     *
     * @param <T>
     * @param type
     * @param next
     * @param error
     * @return
     */
    public <T> Disposable doSubscribe(Class<T> type, Consumer<T> next, Consumer<Throwable> error){
        return getObservable(type)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(next,error);
    }
    /**
     * 是否已有觀察者訂閱
     *
     * @return
     */
    public boolean hasObservers() {
        return mSubject.hasObservers();
    }
    /**
     * 儲存訂閱後的disposable
     * @param o
     * @param disposable
     */
    public void addSubscription(Object o, Disposable disposable) {
        if (mSubscriptionMap == null) {
            mSubscriptionMap = new HashMap<>();
        }
        String key = o.getClass().getName();
        if (mSubscriptionMap.get(key) != null) {
            mSubscriptionMap.get(key).add(disposable);
        } else {
            //一次性容器,可以持有多個並提供 新增和移除。
            CompositeDisposable disposables = new CompositeDisposable();
            disposables.add(disposable);
            mSubscriptionMap.put(key, disposables);
        }
    }

    /**
     * 取消訂閱
     * @param o
     */
    public void unSubscribe(Object o) {
        if (mSubscriptionMap == null) {
            return;
        }

        String key = o.getClass().getName();
        if (!mSubscriptionMap.containsKey(key)){
            return;
        }
        if (mSubscriptionMap.get(key) != null) {
            mSubscriptionMap.get(key).dispose();
        }

        mSubscriptionMap.remove(key);
    }
}
  • 使用

傳送事件

RxBus rxBus = RxBus.getIntanceBus();
//傳送事件
rxBus.post(new RxBusMessage("1"));
rxBus.post(new RxBusMessage("2"));

接受事件

private void initRxBus() {
        rxBus = RxBus.getIntanceBus();
        registerRxBus(RxBusMessage.class, new Consumer<RxBusMessage>() {
            @Override
            public void accept(@NonNull RxBusMessage rxBusMessage) throws Exception {
             //根據事件型別進行處理
                if(TextUtils.equals(rxBusMessage.getMessage(),"1")){
                    mTvRebus.setText(rxBusMessage.getMessage());
                }else if(TextUtils.equals(rxBusMessage.getMessage(),"2")){
                    rx2.setText(rxBusMessage.getMessage());
                }
            }
        });
    }

//註冊
    public <T> void registerRxBus(Class<T> eventType, Consumer<T> action) {
        Disposable disposable = rxBus.doSubscribe(eventType, action, new Consumer<Throwable>() {
            @Override
            public void accept(@NonNull Throwable throwable) throws Exception {
                Log.e("NewsMainPresenter", throwable.toString());
            }
        });
        rxBus.addSubscription(this,disposable);
    }

銷燬事件


 public void unregisterRxBus() {
        rxBus.unSubscribe(this);
    }
@Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterRxBus();
    }

效果

最後

有什麼不對的地方敬請指正!大家一起進步撒!

拼搏在技術道路上的一隻小白

相關推薦

基於RxJava2的RxBus,打造屬於自己EventBus

前言 由於最近在學RxJava2,同樣避免不了使用Rxbus,但是RxJava1到RxJava2還是有很大的變化的,例如:在 2.x 中 Observable 不支援背壓了,將用一個全新的 Flowable 來支援背壓,Consumer和BiConsumer對

打造屬於自己的instagram!

簡介 專案地址 打造屬於你自己的instagram! 技術棧 react全家桶 typescript ant design egg.js mysql 前後端分離開發模式,前端專案與後端專案屬於不同的工程 // instagram/client 前端工

打造屬於自己的BaseAdapter

轉載請註明出處:http://blog.csdn.net/KevinsCSDN/article/details/51747631 今天看到隊友寫的Adapter,這麼多重複的程式碼,這也能忍???反正我是不能忍,於是動手將ListView的adapter封裝了

Oracle APEX 系列文章3:在阿里雲上打造屬於自己的APEX完整開發環境 (安裝CentOS, Tomcat, Nginx)

引言 在這一章節裡,我們將一起動手安裝CentOS 7作業系統、Tomcat以及Nginx,併為後面的安裝做一些初始化設定。 安裝配置CentOS 7 在阿里雲控制檯購買並啟動CentOS 之前說過,我們選擇阿里雲作為雲提供商。註冊

android Toast大全(五種情形)建立屬於自己的Toast

right 其它 activity make div ins case tco title 搬運而來,如有雷同。絕非意外! Toast用於向用戶顯示一些幫助/提示。以下我做了5中效果,來說明Toast的強大,定義一個屬於你自己的Toast。

屬於自己的自動化框架思路

基礎 學什麽 梳理 程序員 一個 維護 das selenium 去百度 前言 說起自動化,最先想到的應該就是一些編碼技術了。 比如至少會一種語言:java、python、js、c++、vb、等等; 用來設計測試用例和腳本框架,比如至少熟悉一種框架或工具:

私人訂制——屬於自己的Linux

war sta /usr 移植 工作 ble 自由 lib64 guess 一、前言   Linux操作系統至1991年10月5日誕生以來,就其開源性和自由性得到了很多技術大牛的青睞,每個Linux愛好者都為其貢獻了自己的一份力,不管是在Linux內核還是開源軟件等方面,

感覺logo不給力? Python十分鐘制作屬於自己的個性logo

python自學 Python項目實戰 Python詞雲 歡迎大家訂閱公眾號:Python從程序猿到程序員詞雲的使用相信大家已經不陌生了,使用很簡單,直接調用wordcloud包就可以了。它的主要功能是根據文本詞匯和詞匯頻率生成圖片,從中可以直觀的看出各個詞匯所占比重。最近正好想做一個人的logo

在Linux下搭建屬於自己的git伺服器(MAC版)

環境說明 本地mac系統,一般都有git程式安裝(如果沒有則使用:brew install git) 伺服器版本是ubuntu-14.04 直入主題 ​ 使用mac終端遠端連線linux伺服器(命令:ssh [伺服器ip], 之後輸入伺服器密碼)預設都是ro

新媒體內容創作的3個超實用萬能開頭金句!打造屬於的10萬+創意素材 | 黎想

大家好!我是藝形藝意工作室創始人,騰訊網、百度網、今日頭條、搜狐網等網站知名專欄作者,《新媒體推廣運營實戰大全》作者黎想,百度單篇推文10萬+。曾結合親身經理給大家分享一位優秀的新媒體運營人員如何通過"四步引爆法"策劃出引爆眾人蔘與的推廣活動等文章,引發了眾多新媒體從業者的共鳴。

定製屬於自己的ViewEngine(一套邏輯多套UI)

ASP.NET MVC出來這麼久了,心中卻又很多的疑惑:為什麼所有的View都要放在Views目錄下? 為什麼Shared資料夾下面的頁面可以被共享? 為什麼Page既可以是*.cshtml,也可以是*.aspx?  其實上面的幾個問題歸結起來都是檢視引擎的功效。 在傳統的ASP.NET中,可能還沒有

我用小幫軟體幫定製屬於自己的專利管理應用工具....專利定製

你還在用Excel表格管理的各種專利資訊嗎? 為了儲存一些專利的資訊,如申請號、申請時間、名稱、申請人等,你勤奮地手工輸入,一個欄位一個欄位切來換去,雖然打字很快,但工作效率並不高,繁瑣費時間。 有一款能夠合理的管理自有專利的軟體工具,該多好! 你的問題,博為小幫軟體機器人都可以解

生產力:編寫屬於自己的日誌分析器(3)

這一節講解如何擴充套件Scintilla,用來在右側滾動條區域增加各種標記(不同形狀和顏色)。這種在滾動條上顯示標記的做法在一些主流編輯器上很流行,比如XCode用紅色標記編譯error,用黃色標記編譯warning(參見下圖右側滾動條區域): Scintilla本並不

動手製作屬於自己的WIN PE3.0

5、提交儲存映像修改命令:Dism /unmount-Wim /MountDir:\mywinpe\mount /Commit這條命令執行,要等一會兒,執行結果如下圖:執行完後,mount目錄會被自動清空,相當於又“壓縮”回去。三、生成ISO映像根據windows PE使用者指南介紹,如果是製作U盤版的WIN

從零開始做遠控 簡介篇 做一個屬於自己的遠控

做一個屬於你自己的遠控:先對大家說句抱歉,上次答應帶大家一起做遠控但因為我的個人原因讓課程中途斷了,這次我答應大家一定要把這教程完成。你在看著課程之前你必須掌握c/c++,qt,win32 api。不用精通,懂就可以了。先向你們簡單講解下什麼叫遠端控制,就是在別人不知情的情況

利用rpmbuild打包定製屬於自己的RPM包

       這個是自己寫在CSDN上寫的第一個技術部落格, 因為最近自己在研究rpm打包. 今天把它分享出來哈~~ rpm的優勢就是安裝和後期升級方便快捷,無需再次手動編譯原始碼。節省很多時間。. 這裡已Nginx

Android網路程式設計之搭建一個屬於自己的簡單servlet服務端。

部署一個自己的一個簡單servlet服務端有以下幾步: 1.jdk的安裝就不說啦。這裡我們將演示的是在Eclipse裡面釋出專案,要想釋出一個專案,首先我們要有一個tomcat,去官網下載或者百度都可以,下載好之後解壓到任意目錄,然後再eclipse裡面進行配

使用XAMPP和Wordpress搭建一個屬於自己的網站

你好,從今天開始,我將為大家帶來一些我學習SEO和建站的免費教程,今天為大家帶來的是如何用XAMPP搭建一個屬於你自己的網站。來到這裡,可以說很多在百度上已經過時了的資料需要總結的資料這裡都有,你只要按照我的教程來好的廢話不多說了現在開始教程。 首先我們要明白一些問題

如何建立屬於自己的域名郵箱

作者:潘佳宇         出處:騰雲閣文章 ------------------------------------------------------------- 1.開啟騰訊雲->域名管理->域名註冊->註冊了一個域名網址 3.建立域

自定義瀏覽器滾動條的樣式,打造屬於的滾動條風格

前段時間,到網上找素材時,看到了一個很個性的滾動條式,開啟Chrome的除錯工具看了一下,發現不是用JavaScript來模擬實現的,覺得有必要折騰一下。於是在各大瀏覽器中對比了一下,發現只用Chrome適用,也就是說這個用的是Chrome的私有CSS屬性。便百之谷之後,發現原來不僅僅只用Chrome,其它的