#Android# RxJava入門指南

知識(shí)框架(腦圖)

RxJava腦圖

出現(xiàn)背景

  • Android中UI主線程的限制和應(yīng)用流暢度的要求使得異步任務(wù)繁多,容易導(dǎo)致回調(diào)地獄(Callbak Hell)
  • 之前的Handler和AsyncTask解決方案都不很理想
  • EventBus缺乏對(duì)事件的處理虚汛,不夠靈活

解決思路

  • 使用觀察者模式解耦
  • 使用可觀測(cè)的序列來(lái)組成異步的局劲、基于事件的程序庫(kù)
  • 即使邏輯復(fù)雜色乾,也要保持程序的簡(jiǎn)潔性
RxJava設(shè)計(jì)思路

具體步驟

(1)Observable->Subscriber 通用版

// 可觀測(cè)者,或者稱為被觀察者
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>(){
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Hello RxJava."); //觸發(fā)普通事件
        subscriber.onCompleted(); //觸發(fā)該方法作為事件隊(duì)列完結(jié)的標(biāo)志
    }
});
// 訂閱者
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onCompleted() { //事件隊(duì)列完結(jié)
    }
    @Override
    public void onError(Throwable e) { //事件隊(duì)列異常
    }
    @Override
    public void onNext(String s) { //普通事件
        System.out.println(s);
    }
};
// 訂閱事件,形成一個(gè)Subscription
observable.subscribe(subscriber);

(2)Observable->Subscriber 簡(jiǎn)單版

//v1: 使用Subscriber(訂閱者)
Observable.just("Hello RxJava").subscribe(new Subscriber<String>() {
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
    @Override
    public void onNext(String s) {
        System.out.println(s);
    }
});
//v2:使用Observer(觀察者)
// 區(qū)別于Subscriber,沒(méi)有unsubscribe坛芽、isUnsubscribed和onStart方法
Observable.just("Hello RxJava").subscribe(new Observer<String>() {
    @Override
    public void onCompleted() {
    }
    @Override
    public void onError(Throwable e) {
    }
    @Override
    public void onNext(String s) {
        System.out.println(s);
    }
});
//v3:使用Action1,不關(guān)心是否結(jié)束和發(fā)生錯(cuò)誤
Observable.just("Hello RxJava").subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        System.out.println(s);
    }
});

(3)取消訂閱與檢查訂閱狀態(tài)

Subscription subscription = Observable.just("Hello RxJava").subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        System.out.println(s);
    }
});
// 取消訂閱
subscription.unsubscribe();
// 檢查是否取消訂閱
System.out.println(subscription.isUnsubscribed());

(4)事件變換

所謂變換翼抠,就是將事件序列中的對(duì)象或整個(gè)序列進(jìn)行加工處理咙轩,轉(zhuǎn)換成不同的事件或事件序列。
map():一對(duì)一變換阴颖,將一個(gè)對(duì)象直接變換成另一個(gè)對(duì)象
flatMap():將傳入的對(duì)象作為泛型創(chuàng)建一個(gè)Observable對(duì)象活喊,激活該Observable對(duì)象并匯入同一個(gè)Observable對(duì)象

map栗子:

//"#Lshare" -> "<h1>Lshare</h1>"
Observable.just("#Lshare").map(new Func1<String, String>() {
    @Override
    public String call(String s) {
        if (s.startsWith("#")) {
            return "<h1>" + s.substring(1) + "</h1>";
        }
        return s;
    }
}).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        System.out.println(s);
    }
});

flatMap栗子:

Student student = new Student("Lshare",
            new Course[]{new Course("404", "Java"), new Course("200", "Android")});
    Observable.just(student).flatMap(new Func1<Student, Observable<Course>>() {
        @Override
        public Observable<Course> call(Student student) {
            if (student.name.equals("Lshare")) { //這家伙的話要多學(xué)點(diǎn),哈哈~
                Course[] newCourses = new Course[student.courses.length + 1];
                newCourses[newCourses.length - 1] = new Course("100", "RxJava");
                System.arraycopy(student.courses, 0, newCourses, 0, newCourses.length - 1);
                return Observable.from(newCourses);
            }
            return Observable.from(student.courses);
        }
    }).subscribe(new Action1<Course>() {
        @Override
        public void call(Course course) {
            System.out.println(course.id + " - " + course.name + " ");
        }
    });
}

附帶實(shí)體類:

class Student {
    public String name;
    public Course[] courses ;
    public Student(String name , Course[] courses) {
        this . name = name ;
        this. courses = courses;
    }
}
class Course {
    public String id;
    public String name ;
    public Course(String id , String name) {
        this . id = id ;
        this. name = name;
    }
}

(5)線程控制

在不指定線程的情況下量愧,RxJava遵循的是線程不變的原則钾菊;當(dāng)需要線程切換時(shí),可以使用Scheduler(線程調(diào)度器)偎肃。

  • Schedulers.immediate(): 直接在當(dāng)前線程運(yùn)行煞烫,相當(dāng)于不指定線程。這是默認(rèn)的 Scheduler累颂。
  • Schedulers.newThread(): 總是啟用新線程红竭,并在新線程執(zhí)行操作。
  • Schedulers.io(): I/O 操作(讀寫(xiě)文件、讀寫(xiě)數(shù)據(jù)庫(kù)茵宪、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多瘦棋,區(qū)別在于 io() 的內(nèi)部實(shí)現(xiàn)是是用一個(gè)無(wú)數(shù)量上限的線程池稀火,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率赌朋。不要把計(jì)算工作放在 io() 中凰狞,可以避免創(chuàng)建不必要的線程。
  • Schedulers.computation(): CPU 密集計(jì)算所使用的 Scheduler沛慢,例如圖形的計(jì)算赡若,不會(huì)被 I/O 等操作限制 。這個(gè) Scheduler 使用的固定的線程池团甲,大小為 CPU 核數(shù)逾冬。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時(shí)間會(huì)浪費(fèi) CPU躺苦。
  • AndroidSchedulers.mainThread():它指定的操作將在 Android 主線程運(yùn)行身腻。

Observerable提供用來(lái)指定線程的方法:

  • subscribeOn() : 指定事件產(chǎn)生的線程,訂閱然后激活了事件
  • **observerOn() : **指定事件消費(fèi)的線程匹厘,Subscriber運(yùn)行的線程
Observable.just(1, 2, 3)
        .observeOn(Schedulers.io())
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                System.out.println(integer);
            }
        });

(6)進(jìn)階:認(rèn)識(shí)Subject

Subject就是一個(gè)Observable也是一個(gè)Observer嘀趟,因?yàn)樗黣xtends了Observable,然后又implements了Observer愈诚。
有一個(gè)抽象方法:hasObservers()返回值表示是否至少有一個(gè)Observer訂閱了該Subject她按。

有四種Subject類型:

類型 訂閱時(shí)行為 圖解 發(fā)生錯(cuò)誤時(shí)行為
**AsyncSubject ** 只在原始Observable完成后,發(fā)射來(lái)自原始Observable的最后一個(gè)值炕柔。(如果原始Observable沒(méi)有發(fā)射任何值酌泰,AsyncObject也不發(fā)射任何值)。
AyncSubject
只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知
BehaviorSubject 發(fā)射原始Observable最近發(fā)射的數(shù)據(jù)(如果此時(shí)沒(méi)有收到任何數(shù)據(jù)汗唱,它會(huì)發(fā)送一個(gè)默認(rèn)值)宫莱,然后繼續(xù)發(fā)射后續(xù)的來(lái)自原始Observable的數(shù)據(jù)。
BehaviorSubject
只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知
PublishSubject 將自訂閱時(shí)間點(diǎn)之后的數(shù)據(jù)發(fā)射給觀察者哩罪,之前的數(shù)據(jù)不再發(fā)射授霸。
PublishSubject
只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知
ReplaySubject 發(fā)射所有來(lái)自原始Observable的數(shù)據(jù),而不管是什么時(shí)候開(kāi)始訂閱际插。
ReplaySubject
只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知

Q&A

問(wèn)題1:RxJava如何與Retrofit配合使用碘耳?

// todo

參考文檔

  1. RxJava初探
  2. 給 Android 開(kāi)發(fā)者的 RxJava 詳解
  3. ReactiveX/RxJava文檔中文版
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市框弛,隨后出現(xiàn)的幾起案子辛辨,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斗搞,死亡現(xiàn)場(chǎng)離奇詭異指攒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)僻焚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門允悦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人虑啤,你說(shuō)我怎么就攤上這事隙弛。” “怎么了狞山?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵全闷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我萍启,道長(zhǎng)总珠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任伊约,我火速辦了婚禮姚淆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屡律。我一直安慰自己腌逢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布超埋。 她就那樣靜靜地躺著搏讶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霍殴。 梳的紋絲不亂的頭發(fā)上媒惕,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音来庭,去河邊找鬼妒蔚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛月弛,可吹牛的內(nèi)容都是我干的肴盏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帽衙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菜皂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起厉萝,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恍飘,失蹤者是張志新(化名)和其女友劉穎榨崩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體章母,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡母蛛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乳怎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溯祸。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舞肆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情博杖,我是刑警寧澤椿胯,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站剃根,受9級(jí)特大地震影響哩盲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狈醉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一廉油、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苗傅,春花似錦抒线、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至逊桦,卻和暖如春眨猎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背强经。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工睡陪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匿情。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓兰迫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親码秉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逮矛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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