RxJava學(xué)習(xí)

什么是RxJava?

要知道什么是RxJava首先要去了解下Rx始衅。Rx全稱Reactive Extensions,直譯過來就是響應(yīng)式擴(kuò)展。
RxJava是基于觀察者模式思喊,他是一種編程模型藏姐,目標(biāo)是提供一致的編程接口,幫助開發(fā)者方便的處理異步數(shù)據(jù)流响驴。

ReactiveX.io給的定義是,Rx是一個使用可觀察數(shù)據(jù)流進(jìn)行異步編程的編程接口撕蔼,ReactiveX結(jié)合了觀察者模式豁鲤、迭代器模式和函數(shù)式編程的精華。Rx已經(jīng)滲透到了各個語言中鲸沮,有了Rx所以才有了 RxJava琳骡,Rx.NET、RxJS讼溺、RxSwift日熬、Rx.rb、RxPHP等等肾胯,更詳細(xì)的可以去這里看看languages

那么RxJava到底是什么呢?我對他的理解就是對于java語言的異步的響應(yīng)式編程庫。

簡單說下什么是響應(yīng)式編程

舉個簡單的栗子耘纱;

    A=B+C

A被賦值為B和C的和敬肚,這是如果B的值發(fā)生變化,A的值并不會發(fā)生變化束析。而如果我們運(yùn)用一種機(jī)制艳馒,當(dāng)B或者C發(fā)送變化,A的值也隨之變化员寇,這就是響應(yīng)式弄慰。

關(guān)于響應(yīng)式的更多更多了解點(diǎn)擊這里傳送門

聊聊RxJava的觀察者模式

剛剛已經(jīng)了解了RxJava是有RX衍生過來的,所以RxJava也是基于觀察者模式蝶锋。就好比一個害羞的小男孩陆爽,暗戀一個小女孩,女生的一舉一動他都認(rèn)真仔細(xì)的觀察扳缕,女孩餓了慌闭,渴了别威。。驴剔。最后終于看著女孩被別人牽走啦省古。所以不能只說觀察,也要行動啊丧失。

上例中的女孩就是被觀察者豺妓,男孩則是觀察者。對應(yīng)RxJava中布讹,有這幾個基本概念:

  • Observable (可觀察者琳拭,即被觀察者)
  • Observer (觀察者)
  • subscribe (訂閱)
  • 事件

Observable 和 Observer 通過 subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系,從而 Observable 可以在需要的時候發(fā)出事件來通知 Observer炒事。

與傳統(tǒng)觀察者模式不同臀栈, RxJava 的事件回調(diào)方法除了普通事件 onNext() 
(相當(dāng)于 onClick() / onEvent())之外,還定義了兩個特殊的事件:onCompleted() 和 onError()挠乳。

onCompleted(): 事件隊(duì)列完結(jié)权薯。RxJava 不僅把每個事件單獨(dú)處理,還會把它們看做一個隊(duì)列睡扬。
RxJava 規(guī)定盟蚣,當(dāng)不會再有新的 onNext() 發(fā)出時,需要觸發(fā) onCompleted() 方法作為標(biāo)志卖怜。

onError(): 事件隊(duì)列異常屎开。在事件處理過程中出異常時,onError() 會被觸發(fā)马靠,同時隊(duì)列自動終止奄抽,不允許再有事件發(fā)出。

在一個正確運(yùn)行的事件序列中, onCompleted() 和 onError() 有且只有一個甩鳄,并且是事件序列中的最后一個逞度。需要注意的是,onCompleted() 和 onError() 二者也是互斥的妙啃,即在隊(duì)列中調(diào)用了其中一個档泽,就不應(yīng)該再調(diào)用另一個。

RxJava API的使用

(1) 創(chuàng)建 Observer

observer_create.png

(2) 創(chuàng)建 Observable

observable_create.png

也可以利用just或者from快速創(chuàng)建observable

  • just(T...): 將傳入的參數(shù)依次發(fā)送出來揖赴。
    Observable observable = Observable.just("Hello", "Hi", "Aloha");
    // 將會依次調(diào)用:
    // onNext("Hello");
    // onNext("Hi");
    // onNext("Aloha");
    // onCompleted();
  • from(T[]) / from(Iterable<? extends T>) : 將傳入的數(shù)組或 Iterable 拆分成具體對象后馆匿,依次發(fā)送出來。
    String[] words = {"Hello", "Hi", "Aloha"};
    Observable observable = Observable.from(words);
    // 將會依次調(diào)用:
    // onNext("Hello");
    // onNext("Hi");
    // onNext("Aloha");
    // onCompleted();

(3) Subscribe (訂閱)

創(chuàng)建了 Observable 和 Observer 之后燥滑,再用 subscribe() 方法將它們聯(lián)結(jié)起來渐北,整條鏈子就可以工作了。代碼形式很簡單:

observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);

(4)線程控制Scheduler

Schedulers.png

在調(diào)用Scheduler的時候有這兩個方法

  • subscribeOn() : 設(shè)置的是被觀察者所做的一些操作的線程(發(fā)送事件的線程)
  • observeOn() : 設(shè)置的是觀察者被通知之后在哪個線程操作(接收事件的線程)

多次指定發(fā)送事件(上游)的線程只有第一次指定的有效, 也就是說多次調(diào)用subscribeOn() 只有第一次的有效, 其余的會被忽略.

多次指定接收(下游)的線程是可以的, 也就是說每調(diào)用一次observeOn() , 下游的線程就會切換一次.

RxJava 操作符

  • map
    Map操作符對原始Observable發(fā)射的每一項(xiàng)數(shù)據(jù)應(yīng)用一個你選擇的函數(shù)突倍,然后返回一個發(fā)射這些結(jié)果的Observable腔稀。
map.png

例:得到多個Student對象中的name盆昙,保存到nameList中

    Observable.just(student1, student2, student2)
                    //使用map進(jìn)行轉(zhuǎn)換,參數(shù)1:轉(zhuǎn)換前的類型焊虏,參數(shù)2:轉(zhuǎn)換后的類型
                    .map(new Func1<Student, String>() {
                        @Override
                        public String call(Student i) {
                            String name = i.getName();//獲取Student對象中的name
                            return name;//返回name
                        }
                    })
                    .subscribe(new Action1<String>() {
                        @Override
                        public void call(String s) {
                            nameList.add(s);
                        }
                    });

上例淡喜,map將原來的student數(shù)據(jù)源轉(zhuǎn)化為String name 發(fā)送出去了,觀察者拿到的就是name

  • FlatMap
    FlatMap將一個發(fā)射數(shù)據(jù)的Observable變換為多個Observables诵闭,然后將它們發(fā)射的數(shù)據(jù)合并后放進(jìn)一個單獨(dú)的Observable

  • concatMap
    它類似于最簡單版本的flatMap炼团,但是它按次序連接而不是合并那些生成的Observables,然后產(chǎn)生自己的數(shù)據(jù)序列疏尿。

flatMap.png

例如瘟芝,上面是打印每個學(xué)生的名字,這邊我們需要打印出每個學(xué)生的課程名稱,一個學(xué)生有多個課程

      /**
         * 學(xué)生類
         */
        class Student {
            private String name;//姓名
            private List<Course> coursesList;//所修的課程
            ...
        }
        /**
         * 課程類
         */
        class  Course {
            private String name;//課程名
            private String id;
            ...
        }

利用flatMap變化一下:

     List<Student> students = new ArrayList<Student>();
            students.add...
            ...

            Observable.from(students)
                    .flatMap(new Func1<Student, Observable<Course>>() {
                        @Override
                        public Observable<Course> call(Student student) {
                            return Observable.from(student.getCoursesList());
                        }
                    })
                    .subscribe(new Action1<Course>() {
                        @Override
                        public void call(Course course) {
                            Log.i(TAG, course.getName());
                        }
                    });

上述例子中褥琐,數(shù)據(jù)源轉(zhuǎn)化是這樣的:

 student  ->  course1,course2...  -> 利用from()將所有的course放入一個observerble中發(fā)送出去

 接收消息的數(shù)據(jù)源就變成 List<Course>課程的列表,直接打印名稱
  • zip
    通過一個函數(shù)將多個Observables的發(fā)射物結(jié)合到一起锌俱,基于這個函數(shù)的結(jié)果為每個結(jié)合體發(fā)射單個數(shù)據(jù)項(xiàng)。
zip.png

使用場景:
比如一個界面需要展示用戶的一些信息, 而這些信息分別要從兩個服務(wù)器接口中獲取, 而只有當(dāng)兩個都獲取到了之后才能進(jìn)行展示, 這個時候就可以用Zip了:

Compose操作符是將源Observable按照自定義的方式轉(zhuǎn)化成另外一個新的Observable敌呈∶澈辏可以這么說compose是對Observable進(jìn)行操作的而lift是對Subscriber進(jìn)行操作的,作用點(diǎn)是不同的磕洪。
(這里的lift類似map吭练,將數(shù)據(jù)類型轉(zhuǎn)化)

  • fliter
    只發(fā)射通過了謂詞測試的數(shù)據(jù)項(xiàng)
filter.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市析显,隨后出現(xiàn)的幾起案子鲫咽,更是在濱河造成了極大的恐慌,老刑警劉巖谷异,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件分尸,死亡現(xiàn)場離奇詭異,居然都是意外死亡歹嘹,警方通過查閱死者的電腦和手機(jī)寓落,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荞下,“玉大人,你說我怎么就攤上這事史飞〖饣瑁” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵构资,是天一觀的道長抽诉。 經(jīng)常有香客問我,道長吐绵,這世上最難降的妖魔是什么迹淌? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任河绽,我火速辦了婚禮,結(jié)果婚禮上唉窃,老公的妹妹穿的比我還像新娘耙饰。我一直安慰自己,他們只是感情好纹份,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布苟跪。 她就那樣靜靜地躺著,像睡著了一般蔓涧。 火紅的嫁衣襯著肌膚如雪件已。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天元暴,我揣著相機(jī)與錄音篷扩,去河邊找鬼。 笑死茉盏,一個胖子當(dāng)著我的面吹牛鉴未,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播援岩,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼歼狼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了享怀?” 一聲冷哼從身側(cè)響起羽峰,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎添瓷,沒想到半個月后梅屉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳞贷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年坯汤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀愧。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡惰聂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咱筛,到底是詐尸還是另有隱情搓幌,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布迅箩,位于F島的核電站溉愁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏饲趋。R本人自食惡果不足惜拐揭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一撤蟆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堂污,春花似錦家肯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扒披,卻和暖如春值依,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碟案。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工愿险, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人价说。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓辆亏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鳖目。 傳聞我的和親對象是個殘疾皇子扮叨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

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