RxJava基礎一-創(chuàng)建操作符

此篇內容均是來自書籍《RxJava響應式編程》李衍順 著

一彤侍、什么是RxJava?

RxJava是一個非常著名的開源庫饥侵,是ReactiveX(Reactive Extensions)的一種Java實現(xiàn)颖侄。ReactiveX是一種響應式擴展框架萄凤,有很多種實現(xiàn),如RxAndroid, RxJS宋税,RxSwift摊崭,RxRuby,RxCpp,RxGo等。目前RxJava有1.x和2.x兩個主要分支弃甥,分別代表RxJava1和RxJava2爽室。RxJava1發(fā)布的時間比較早, 使用也更廣泛淆攻,所以先來了解下RxJava1阔墩。

RxJava可看作由Observable、Subscriber和Scheduler組成的瓶珊。Subscriber訂閱到Observable啸箫,Obervable會在默認或者指定的Scheduler上工作并產生數據流返回給Subscriber,Subscriber也會在默認或者指定的Scheduler上接收Observable發(fā)送過來的數據流伞芹。Scheduler是對線程的一種抽象忘苛,不同的Scheduler代表 了不同的線程。


image.png

1.1 Observable和Subscriber

Observable提供了subscribe方法唱较, 當有Subscriber通過subscribe方法訂閱到Observable時扎唾, Observable就可以向Subscriber發(fā)送數據流。響應式編程中的事件分為三類:普通事件 南缓,錯誤事件和結束事件胸遇,在Subscriber中有三個方法與這三件事一一對應,Observable會通過調用Subscriber的這三個方法來發(fā)送對應的事件汉形。

  1. onNext:當Observable要發(fā)送普通事件時纸镊,就會調用這個方法。這個方法可被調用0~N次概疆。
  2. onError: 當在Observable內部有異扯和或者錯誤產生時,就可以調用這個方法來向Subscriber發(fā)送錯誤事件岔冀。這個方法只能被調用一次凯旭。
  3. onComplete: 如果Observable已經發(fā)送完所有數據,并且沒有發(fā)生錯誤使套,這時就需要調用這個方法來向Subscriber發(fā)送結束事件罐呼。這個方法只能調用一次,而且和onError是互斥的關系童漩,也就是說調用了onError后就不能調用onComplete 反之亦然弄贿。在onError或者onComplete被調用之后春锋, Observable就失去了作用矫膨, 不能再調用onNext來發(fā)送數據了。

Subscriber還提供了unsubscribe方法, 當Subscriber訂閱到Observable之后侧馅, 可以隨時調用這個方法來終止對Observable的訂閱危尿。

二、在Android工程中引入RxJava

只需要在Gradle配置文件中加入對RxJava的依賴馁痴。但是Android開發(fā)中一般會添加對RxAndroid的依賴谊娇,而RxAndroid已經依賴于RxJava,且一般難以及時更新到最新版的RxJava罗晕,所以如果想使用RxAndroid和最新版本的RxJava济欢,則可以通過下面的配置來導入依賴。

api ('io.reactivex.rxjava2:rxandroid:2.1.0'){
        exclude module:'rxjava2'
    }
api 'io.reactivex.rxjava2:rxjava:2.2.1'

三小渊、RxJava中的操作符

3.1 創(chuàng)建Observable的操作符

3.1.1 range

range操作符創(chuàng)建的Observable將會發(fā)送一個范圍內的數據

Observable.range(0,4)
                .subscribe(new Action1<Integer>(){
                    @Override
                    public void call(Integer integer) {
                        System.out.println(integer);
                    }
                });

結果是:

0 1 2 3

3.1.2 defer和just

defer操作符法褥,只有當Subscriber來訂閱的時候才會創(chuàng)建一個新的Observable對象, 也就是說每次訂閱都會得到一個剛創(chuàng)建的最新的Observable對象酬屉,這可以確保Observable對象里的數據是最新的半等。
just操作符接收某個對象作為輸入,然后會創(chuàng)建一個發(fā)送該對象的Observable呐萨。這個對象可以是一個數字杀饵,一個字符串,數組谬擦,Iterate對象等切距。just是一種非常快捷的創(chuàng)建Observable對象的方法怯屉,在后面的例子中會大量使用蔚舀。
我們通過這兩個操作符創(chuàng)建兩個Observable,這兩個Observable都會將Android系統(tǒng)中的當前時間作為數據發(fā)送锨络。我們將這兩個Observable分別保存在變量deferObservable和justObservable中赌躺。

Observable<Long> deferObservable = getDefer();
    Observable<Long> justObservable = getJust();
    private Observable<Long> getJust() {
        return Observable.just(System.currentTimeMillis());
    }
    private Observable<Long> getDefer() {
        return Observable.defer(new Func0<Observable<Long>>() {
            @Override
            public Observable<Long> call() {
                return getJust();
            }
        });
    }

現(xiàn)在分別對這兩個Observable進行訂閱

private void Just_Defer(){
        for(int i = 0; i<3;i++) {
            deferObservable.subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                    System.out.println("defer: " + aLong);
                }
            });
            justObservable.subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                    System.out.println("just: " + aLong);
                }
            });

        }
    }

輸出結果可以看到defer每次訂閱都會得到Observable發(fā)送的一個全新的當前時間, 而just創(chuàng)建的操作符即使訂閱多次也都會發(fā)出和首次訂閱一樣的數據羡儿。

defer: 1554532535942
just: 1554532535905
defer: 1554532535954
just: 1554532535905
defer: 1554532535954
just: 1554532535905

3.1.3 from

from操作符接收一個對象作為參數來創(chuàng)建Observable礼患,這個參數對象可以是Iterable、Callable掠归、Future和數組等缅叠。 from操作符創(chuàng)建的Observable將發(fā)送參數對象里的數據, 其創(chuàng)建方式類似于just操作符虏冻,但是just操作符創(chuàng)建的Observable會將整個參數對象作為數據一下子發(fā)送出去肤粱。 比如說參數對象是一個含有10個數字的數組,使用from創(chuàng)建的Observable就會發(fā)送10次厨相, 每次發(fā)送一個數字领曼,而使用just創(chuàng)建的Observable會一次就將整個數組發(fā)送出去鸥鹉。
首先創(chuàng)建一個數組和一個List, 分別存儲0~5的整數庶骄,然后使用from操作符分別以數組和List作為輸入參數創(chuàng)建兩個Observable對象毁渗。之后分別訂閱,會輸出什么結果呢单刁?

Integer[] arrays = {0,1,2,3,4,5};
    List<Integer> list = new ArrayList<>();
    private Observable<Integer> FromArray() {
        return Observable.from(arrays);
    }
    private Observable<Integer> FromIterable() {
        for(int i = 0;i <= 5; i++) {
            list.add(i);
        }
        return Observable.from(list);
    }
    private void From(){
        FromArray().subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                System.out.println("FromArray: " + integer);
            }
        });
        FromIterable().subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                System.out.println("FromIterable: " + integer);
            }
        });
    }
FromArray: 0
FromArray: 1
FromArray: 2
FromArray: 3
FromArray: 4
FromArray: 5
FromIterable: 0
FromIterable: 1
FromIterable: 2
FromIterable: 3
FromIterable: 4
FromIterable: 5

3.1.4 interval

interval所創(chuàng)建的Observable對象會從0開始灸异, 每隔固定的時間發(fā)送一個數字。需要注意的是羔飞, 這個對象時運行在computation Scheduler中的肺樟,所以在Android開發(fā)中 ,如果需要在UI中顯示結果逻淌, 則需要在主線程中訂閱儡嘶。
代碼通過interval操作符創(chuàng)建了一個Observable, 創(chuàng)建的Observable將會以1秒為間隔不斷地發(fā)送數據恍风,因為我們需要更新UI蹦狂,所以在主線程中進行訂閱。這里的AndroidSchedulers.mainThread()屬于RxAndroid庫朋贬, RxAndroid是Jake Wharton在Android平臺上開發(fā)的一個對RxJava的擴展凯楔。最后創(chuàng)建一個Subscriber對象對這個Observable對象進行訂閱, 就會每秒輸出一個從0開始遞增的數據锦募。

private void interval(){
        Subscriber<Long> subscriber = new Subscriber<Long>() {
            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("onError: " + e.getMessage());
            }

            @Override
            public void onNext(Long aLong) {
                System.out.println("onNext:" + aLong);
            }
        };

        Observable.interval(0,10, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

最后結果是摆屯,原因不知道

onError: null

最后,由于interval操作符創(chuàng)建的Observable對象會不停地發(fā)送數據糠亩,所以當我們不再需要它的數據時要調用unSubscribe方法進行反訂閱虐骑,反訂閱后Observable將會停止發(fā)送數據

subscriber.unsubscribe();

3.1.5 repeat和timer

repeat操作符可以讓Observable對象發(fā)送的數據重復發(fā)送N次, 我們可以指定其發(fā)送的次數赎线。timer操作符創(chuàng)建的Observable會在指定時間后發(fā)送一個數字0廷没, 注意其默認也是運行在computation scheduler 上。
下面我們來創(chuàng)建一個發(fā)送整數1垂寥,2颠黎,3的源Observable, 并使用repeat操作符在源Observable的基礎上創(chuàng)建一個新的Observable滞项,使其重復發(fā)送數據3次狭归。另外使用timer創(chuàng)建一個會在1秒后發(fā)送數據的Observable。

private void Repeat_Timer() {
        Observable.just(1,2,3).repeat(3)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        System.out.println("repeat: " + integer);
                    }
                });

        Observable.timer(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        System.out.println("timer: " + aLong);
                    }
                });
    }

結果呢文判,后面的這個報空指針異常过椎,還沒找到原因;正常timer操作符創(chuàng)建的Observable在訂閱1秒后發(fā)送一個數據0.

repeat: 1
repeat: 2
repeat: 3
repeat: 1
repeat: 2
repeat: 3
repeat: 1
repeat: 2
repeat: 3

另外還有幾個非常簡單的創(chuàng)建操作符戏仓,如naver疚宇、empty竞惋、throw等,請移步查看官方文檔灰嫉。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嗓奢,隨后出現(xiàn)的幾起案子讼撒,更是在濱河造成了極大的恐慌,老刑警劉巖股耽,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件根盒,死亡現(xiàn)場離奇詭異,居然都是意外死亡物蝙,警方通過查閱死者的電腦和手機炎滞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诬乞,“玉大人册赛,你說我怎么就攤上這事≌鸺担” “怎么了森瘪?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長票堵。 經常有香客問我扼睬,道長,這世上最難降的妖魔是什么悴势? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任窗宇,我火速辦了婚禮,結果婚禮上特纤,老公的妹妹穿的比我還像新娘军俊。我一直安慰自己,他們只是感情好捧存,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布蝇完。 她就那樣靜靜地躺著,像睡著了一般矗蕊。 火紅的嫁衣襯著肌膚如雪短蜕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天傻咖,我揣著相機與錄音朋魔,去河邊找鬼。 笑死卿操,一個胖子當著我的面吹牛警检,可吹牛的內容都是我干的孙援。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼扇雕,長吁一口氣:“原來是場噩夢啊……” “哼拓售!你這毒婦竟也來了?” 一聲冷哼從身側響起镶奉,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤础淤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哨苛,有當地人在樹林里發(fā)現(xiàn)了一具尸體鸽凶,經...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年建峭,在試婚紗的時候發(fā)現(xiàn)自己被綠了玻侥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡亿蒸,死狀恐怖凑兰,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情边锁,我是刑警寧澤票摇,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站砚蓬,受9級特大地震影響矢门,放射性物質發(fā)生泄漏。R本人自食惡果不足惜灰蛙,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一祟剔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摩梧,春花似錦物延、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至笙纤,卻和暖如春耗溜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背省容。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工抖拴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腥椒。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓阿宅,卻偏偏與公主長得像候衍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洒放,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內容

  • 一蛉鹿、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性,函數式最大的好處就是使得數據處理簡潔易...
    BrotherChen閱讀 1,625評論 0 10
  • 一往湿、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性妖异,函數式最大的好處就是使得數據處理簡潔易...
    無求_95dd閱讀 3,123評論 0 21
  • 一、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性煌茴,函數式最大的好處就是使得數據處理簡潔易...
    測天測地測空氣閱讀 637評論 0 1
  • 一、Retrofit詳解 ·Retrofit的官網地址為 : http://square.github.io/re...
    余生_d630閱讀 1,870評論 0 5
  • 轉一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong閱讀 925評論 0 2