Rxjava解析

Rxjava(https://gank.io/post/560e15be2dca930e00da1083#toc_4

(1).Rxjava是一個(gè)用于處理異步和基于事件編程的Java庫(kù).
(2).Rxjava原理就是類似于觀察者模式
觀察者模式面向的需求是:A 對(duì)象(觀察者)對(duì) B 對(duì)象(被觀察者)的某種變化高度敏感结榄,需要在 B 變化的一瞬間做出反應(yīng)。舉個(gè)例子,新聞里喜聞樂見的警察抓小偷,警察需要在小偷伸手作案的時(shí)候?qū)嵤┳ゲ丁T谶@個(gè)例子里叮雳,警察是觀察者,小偷是被觀察者,警察需要時(shí)刻盯著小偷的一舉一動(dòng)段磨,才能保證不會(huì)漏過任何瞬間。程序的觀察者模式和這種真正的『觀察』略有不同耗绿,觀察者不需要時(shí)刻盯著被觀察者(例如 A 不需要每過 2ms 就檢查一次 B 的狀態(tài))苹支,而是采用注冊(cè)(Register)或者稱為訂閱(Subscribe)的方式,告訴被觀察者:我需要你的某某狀態(tài)误阻,你要在它變化的時(shí)候通知我债蜜。 Android 開發(fā)中一個(gè)比較典型的例子是點(diǎn)擊監(jiān)聽器 OnClickListener 。對(duì)設(shè)置 OnClickListener 來說究反, View 是被觀察者寻定, OnClickListener 是觀察者,二者通過 setOnClickListener() 方法達(dá)成訂閱關(guān)系精耐。訂閱之后用戶點(diǎn)擊按鈕的瞬間狼速,Android Framework 就會(huì)將點(diǎn)擊事件發(fā)送給已經(jīng)注冊(cè)的 OnClickListener 。采取這樣被動(dòng)的觀察方式卦停,既省去了反復(fù)檢索狀態(tài)的資源消耗向胡,也能夠得到最高的反饋速度。當(dāng)然惊完,這也得益于我們可以隨意定制自己程序中的觀察者和被觀察者僵芹,而警察叔叔明顯無法要求小偷『你在作案的時(shí)候務(wù)必通知我』

RxJava 有四個(gè)基本概念:Observable (可觀察者,即被觀察者)小槐、 Observer (觀察者)拇派、 subscribe (訂閱)、事件凿跳。Observable 和 Observer 通過 subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系攀痊,從而 Observable 可以在需要的時(shí)候發(fā)出事件來通知 Observer。
//.create創(chuàng)建了一個(gè)Observable<String> 的可發(fā)射事件.
   Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e)  {
                e.onNext("1"); //可以多次調(diào)用
                e.onNext("1"); //可以多次調(diào)用
                e.onComplete();
              //  e.onError(new Exception());
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {     
            }
            @Override
            public void onNext(String s) {
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        });
在 RxJava 的 subscribe 過程中拄显,Observer 也總是會(huì)先被轉(zhuǎn)換成一個(gè) Subscriber 再使用苟径。所以如果你只想使用基本功能,選擇 Observer 和 Subscriber 是完全一樣的躬审。它們的區(qū)別對(duì)于使用者來說主要有兩點(diǎn)棘街。

A:onStart():這是 Subscriber 增加的方法蟆盐。
B: unsubscribe(): 這是 Subscriber 所實(shí)現(xiàn)的另一個(gè)接口 Subscription 的方法,用于取消訂閱,
一般在這個(gè)方法調(diào)用前遭殉,可以使用 isUnsubscribed() 先判斷一下狀態(tài)石挂。 unsubscribe() 這個(gè)方法很重要,因?yàn)樵?subscribe() 之后险污, Observable 會(huì)持有 Subscriber 的引用痹愚,這個(gè)引用如果不能及時(shí)被釋放,將有內(nèi)存泄露的風(fēng)險(xiǎn)蛔糯。所以最好保持一個(gè)原則:要在不再使用的時(shí)候盡快在合適的地方(例如 onPause() onStop() 等方法中)調(diào)用 unsubscribe() 來解除引用關(guān)系拯腮,以避免內(nèi)存泄露的發(fā)生。
(3).操作符
(3-1)just操作符創(chuàng)建Observable被觀察者對(duì)象

 Observable.just(1,2,3,4,5).subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        Log.i(TAG,"onCompleted:");
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.i(TAG,"onNext:"+integer);//執(zhí)行5次
                    }
                });
 

(3-2)map蚁飒,floatmap,filter ,take ,takelast,distinct,skip變換操作符

map操作符----將原Observable發(fā)射出來的數(shù)據(jù)轉(zhuǎn)換為另外一種類型的數(shù)據(jù)
 Observable.just("666").map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return Integer.parseInt(s);
            }
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            } 

            @Override
            public void onNext(Integer integer) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });


floatmap操作符---作用類似于map又比map強(qiáng)大动壤,map是單純的數(shù)據(jù)類型的轉(zhuǎn)換,而flapMap可以將原數(shù)轉(zhuǎn)換成新的Observables淮逻,再將這些Observables的數(shù)據(jù)順序緩存到一個(gè)新的隊(duì)列中琼懊,在統(tǒng)一發(fā)射出來
      List<AccountInfoBean> infoBeans=new ArrayList<>();
        infoBeans.add(new AccountInfoBean());
        infoBeans.add(new AccountInfoBean());
        infoBeans.add(new AccountInfoBean());
        Observable.just(infoBeans).flatMap(new Function<List<AccountInfoBean>, ObservableSource<AccountInfoBean>>() {
            @Override
            public ObservableSource<AccountInfoBean> apply(List<AccountInfoBean> beanList) throws Exception {
              //把beanList中的每個(gè)對(duì)象轉(zhuǎn)換成Observable<AccountInfoBean>
                return Observable.fromIterable(beanList);
            }
        }).subscribe(new Consumer<AccountInfoBean>() {
            @Override
            public void accept(AccountInfoBean accountInfoBean) throws Exception {
                 System.out.println("xxx");//infoBeans中有3個(gè)元素,會(huì)執(zhí)行3次
            }
        });

filter操作符----對(duì)發(fā)射的數(shù)據(jù)做一個(gè)限制爬早,只有滿足條件的數(shù)據(jù)才會(huì)被發(fā)射
//對(duì)發(fā)射的數(shù)據(jù)做一個(gè)限制哼丈,只有滿足條件的數(shù)據(jù)才會(huì)被發(fā)射
                Observable.just("hello","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
                    @Override
                    public Boolean apply(String s) {
                        return s.length()>5;
                    }
                }).subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.i("TAG","filter過濾后的數(shù)據(jù):"+s.toString());
                    }
                });
distinct操作符----過濾掉重復(fù)項(xiàng)
 Observable.just("hello","hello","hello","Rxjava","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
                    @Override
                    public Boolean apply(String s) {
                        return s.length()>5;
                    }
                }).subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.i("TAG","distinct去除重復(fù)之后的數(shù)據(jù):"+s.toString());
                    }
                });
Skip操作符----發(fā)射數(shù)據(jù)時(shí)忽略前N項(xiàng)數(shù)據(jù)(skpiLast忽略后N項(xiàng)數(shù)據(jù))
  Observable.just("hello","Rxjava","Nice to meet you").skip(2).subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.i("TAG","Skip之后的數(shù)據(jù):"+s.toString());
                    }
                });
take操作符----只發(fā)射前N項(xiàng)的數(shù)據(jù)(takeLast與take想反,只取最后N項(xiàng)數(shù)據(jù))
 Observable.just("hello","Rxjava","Nice to meet you").take(2).subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.i("TAG","Take之后的數(shù)據(jù):"+s.toString());
                    }
                });

另外還有一些其他的操作符 range,Interval筛严,empty,error等(http://www.reibang.com/p/eceb6b31d8cb

(3-3).線程調(diào)度Scheduler

 Observable.just(1, 2, 3, 4)
                .subscribeOn(Schedulers.io()) // 指定 subscribe() 發(fā)生在 IO 線程
                .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調(diào)發(fā)生在主線程
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        
                    }

                    @Override
                    public void onNext(Integer integer) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
  • Rxjava解決回調(diào)地獄問題(OkHttp會(huì)導(dǎo)致回調(diào)地獄削祈,無法切換線程)
api.requestFirstData()
    .flatMap(data1 -> api.requestSecondData(data1.getId()))
    .flatMap(data2 -> api.requestThirdData(data2.getToken()))
    .subscribe(
        data3 -> {
            // 處理最終數(shù)據(jù)
        },
        throwable -> {
            // 處理錯(cuò)誤,這里不管是哪個(gè)環(huán)節(jié)出錯(cuò)脑漫,都會(huì)走到這里
        }
    );
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末髓抑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子优幸,更是在濱河造成了極大的恐慌吨拍,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件网杆,死亡現(xiàn)場(chǎng)離奇詭異羹饰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)碳却,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門队秩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昼浦,你說我怎么就攤上這事馍资。” “怎么了关噪?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵鸟蟹,是天一觀的道長(zhǎng)乌妙。 經(jīng)常有香客問我,道長(zhǎng)建钥,這世上最難降的妖魔是什么藤韵? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮熊经,結(jié)果婚禮上泽艘,老公的妹妹穿的比我還像新娘。我一直安慰自己镐依,他們只是感情好匹涮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馋吗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秋秤。 梳的紋絲不亂的頭發(fā)上宏粤,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音灼卢,去河邊找鬼绍哎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鞋真,可吹牛的內(nèi)容都是我干的崇堰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼涩咖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼海诲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起檩互,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤特幔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后闸昨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚯斯,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年饵较,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拍嵌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡循诉,死狀恐怖横辆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茄猫,我是刑警寧澤龄糊,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布逆粹,位于F島的核電站,受9級(jí)特大地震影響炫惩,放射性物質(zhì)發(fā)生泄漏僻弹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一他嚷、第九天 我趴在偏房一處隱蔽的房頂上張望蹋绽。 院中可真熱鬧,春花似錦筋蓖、人聲如沸卸耘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚣抗。三九已至,卻和暖如春瓮下,著一層夾襖步出監(jiān)牢的瞬間翰铡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工讽坏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锭魔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓路呜,卻偏偏與公主長(zhǎng)得像迷捧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胀葱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Rxjava git:地址 RxAndroid git:地址 至于為什么提到RxAndroid漠秋,切換線程時(shí)將會(huì)用到...
    taijielan閱讀 459評(píng)論 0 1
  • 最近開始看Rxjava的源碼,感覺有很多沒見過的操作記錄一下抵屿! 一個(gè)最簡(jiǎn)單的鏈?zhǔn)秸{(diào)用膛堤,無背壓。Observable...
    siyanGo閱讀 626評(píng)論 0 1
  • 一晌该、什么是RxJava? RxJava 在 GitHub 主頁(yè)上的自我介紹是 "a library for com...
    RmondJone閱讀 607評(píng)論 0 1
  • 相關(guān)概念 Android多線程編程的原則: 不要阻塞UI線程; 不要在UI線程之外訪問UI組件; Reactive...
    今陽說閱讀 513評(píng)論 0 1
  • okhttp 1.基本使用 初始化可以添加自定義的攔截器 使用方法 一般的使用大致就是這樣的 2.從OkHttpC...
    Johnson_Coding閱讀 1,014評(píng)論 0 0