RxJava1.x總結(jié)

一桂躏、RxJava概念:

1抢埋、RxJava 有四個基本概念:Observable (可觀察者宋渔,即被觀察者)州疾、 Observer (觀察者)、 subscribe (訂閱)皇拣、事件严蓖。Observable 和 Observer 通過 subscribe() 方法實現(xiàn)訂閱關(guān)系,從而 Observable 可以在需要的時候發(fā)出事件來通知 Observer氧急。

onCompleted(): 事件隊列完結(jié)颗胡。RxJava 不僅把每個事件單獨處理,還會把它們看做一個隊列吩坝。RxJava 規(guī)定毒姨,當不會再有新的 onNext() 發(fā)出時,需要觸發(fā) onCompleted() 方法作為標志钉寝。

onError(): 事件隊列異常弧呐。在事件處理過程中出異常時闸迷,onError() 會被觸發(fā),同時隊列自動終止俘枫,不允許再有事件發(fā)出腥沽。

在一個正確運行的事件序列中, onCompleted() 和 onError() 有且只有一個,并且是事件序列中的最后一個崩哩。需要注意的是巡球,onCompleted() 和 onError() 二者也是互斥的,即在隊列中調(diào)用了其中一個邓嘹,就不應(yīng)該再調(diào)用另一個酣栈。

2、創(chuàng)建 Observer

Subscriber<String> subscriber = new Subscriber<String>() {

? ? @Override

? ? public void onNext(String s) {

? ? ? ? Log.d(tag, "Item: " + s);

? ? }

? ? @Override

? ? public void onCompleted() {

? ? ? ? Log.d(tag, "Completed!");

? ? }

? ? @Override

? ? public void onError(Throwable e) {

? ? ? ? Log.d(tag, "Error!");

? ? }

};

Observer是一個接口汹押,Subscriber是一個抽象類矿筝,Subscriber實現(xiàn)自O(shè)bserver,選擇 Observer 和 Subscriber 是完全一樣的棚贾,區(qū)別在于:

①:onStart():Subscriber中多了個onStart()方法,可以做一些準備工作窖维,他是在Subscribe所發(fā)生的線程被調(diào)用,而不能指定線程妙痹,要在指定的線程來做準備工作铸史,可以使用doOnSubscribe()方法。

②:unsubscribe():這是Subscriber實現(xiàn)另一個接口Subscription中的方法怯伊,用于取消訂閱琳轿。這個方法調(diào)用后,將不再接收事件耿芹,調(diào)用前先isUnsubscribed()判斷狀態(tài)崭篡。在Subscribe()之后,Observable會持有Subscriber的引用吧秕,避免內(nèi)存泄漏的發(fā)生琉闪,調(diào)用unsubscribe()來解除引用關(guān)系。

3砸彬、創(chuàng)建Observable

Observable observable = Observable.create(new Observable.OnSubscribe<String>() {

? ? @Override

? ? public void call(Subscriber<? super String> subscriber) {

? ? ? ? subscriber.onNext("Hello");

? ? ? ? subscriber.onNext("Hi");

? ? ? ? subscriber.onNext("Aloha");

? ? ? ? subscriber.onCompleted();

? ? }

});

create() 方法是 RxJava 最基本的創(chuàng)造事件序列的方法颠毙。基于這個方法砂碉, RxJava 還提供了一些方法用來快捷創(chuàng)建事件隊列蛀蜜,例如:

①:just(T...): 將傳入的參數(shù)依次發(fā)送出來。

Observable observable = Observable.just("Hello", "Hi", "Aloha");

②:from(T[]) / from(Iterable<? extends T>) :

將傳入的數(shù)組或 Iterable 拆分成具體對象后绽淘,依次發(fā)送出來。

String[] words = {"Hello", "Hi", "Aloha"};

Observable observable = Observable.from(words);

上面 just(T...) 的例子和 from(T[]) 的例子闹伪,都和之前的 create(OnSubscribe) 的例子是等價的沪铭。

4壮池、Subscribe (訂閱)

observable.subscribe(observer);

// 或者:

observable.subscribe(subscriber);

5、不完整定義的回調(diào)

Action1<String> onNextAction = new Action1<String>() {

? ? // onNext()

? ? @Override

? ? public void call(String s) {

? ? ? ? Log.d(tag, s);

? ? }

};

Action1<Throwable> onErrorAction = new Action1<Throwable>() {

? ? // onError()

? ? @Override

? ? public void call(Throwable throwable) {

? ? ? ? // Error handling

? ? }

};

Action0 onCompletedAction = new Action0() {

? ? // onCompleted()

? ? @Override

? ? public void call() {

? ? ? ? Log.d(tag, "completed");

? ? }

};

// 自動創(chuàng)建 Subscriber 杀怠,并使用 onNextAction 來定義 onNext()

observable.subscribe(onNextAction);

// 自動創(chuàng)建 Subscriber 椰憋,并使用 onNextAction 和 onErrorAction 來定義 onNext() 和 onError()

observable.subscribe(onNextAction, onErrorAction);

// 自動創(chuàng)建 Subscriber ,并使用 onNextAction赔退、 onErrorAction 和 onCompletedAction 來定義 onNext()橙依、 onError() 和 onCompleted()

observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

說明:

Action0 是 RxJava 的一個接口,它只有一個方法 call()硕旗,這個方法是無參無返回值的

Action1 也是一個接口窗骑,它同樣只有一個方法 call(T param),這個方法也無返回值漆枚,但有一個參數(shù)创译;

6、應(yīng)用場景

①:將字符串數(shù)組 names 中的所有字符串依次打印出來

String[] arr = {"小明","小紅","小花"};

Observable.from(arr).subscribe(new Action1<String>() {

? ? @Override

? ? public void call(String s) {

? ? Log.d("SDK","看看哪里調(diào)用了==="+s);

? ? }

});

②:由 id 取得圖片并顯示

int drawableRes = ...;

ImageView imageView = ...;

Observable.create(new OnSubscribe<Drawable>() {

? ? @Override

? ? public void call(Subscriber<? super Drawable> subscriber) {

? ? ? ? Drawable drawable = getTheme().getDrawable(drawableRes));

? ? ? ? subscriber.onNext(drawable);

? ? ? ? subscriber.onCompleted();

? ? }

}).subscribe(new Observer<Drawable>() {

? ? @Override

? ? public void onNext(Drawable drawable) {

? ? ? ? imageView.setImageDrawable(drawable);

? ? }

? ? @Override

? ? public void onCompleted() {

? ? }

? ? @Override

? ? public void onError(Throwable e) {

? ? ? ? Toast.makeText(activity, "Error!", Toast.LENGTH_SHORT).show();

? ? }

});

二墙基、線程控制--Scheduler(調(diào)度器)

1软族、Scheduler的api

①:Schedulers.immediate(): 直接在當前線程運行,相當于不指定線程残制。這是默認的 Scheduler立砸。

②:Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作初茶。

③:Schedulers.io(): I/O 操作(讀寫文件颗祝、讀寫數(shù)據(jù)庫、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler纺蛆。行為模式和 newThread() 差不多吐葵,區(qū)別在于 io() 的內(nèi)部實現(xiàn)是是用一個無數(shù)量上限的線程池,可以重用空閑的線程桥氏,因此多數(shù)情況下 io() 比 newThread() 更有效率温峭。不要把計算工作放在 io() 中,可以避免創(chuàng)建不必要的線程字支。

④:Schedulers.computation(): 計算所使用的 Scheduler凤藏。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作堕伪,例如圖形的計算揖庄。這個 Scheduler 使用的固定的線程池,大小為 CPU 核數(shù)欠雌。不要把 I/O 操作放在 computation() 中蹄梢,否則 I/O 操作的等待時間會浪費 CPU。

⑤:另外富俄, Android 還有一個專用的 AndroidSchedulers.mainThread()禁炒,它指定的操作將在 Android 主線程運行而咆。

⑥:subscribeOn() 事件產(chǎn)生的線程

⑦:observeOn() 事件消費的線程

三、使用

①:map()? 事件對象的直接變換幕袱,一對一的轉(zhuǎn)化

Observable.just("images/logo.png") // 輸入類型 String

? ? .map(new Func1<String, Bitmap>() {

? ? ? ? @Override

? ? ? ? public Bitmap call(String filePath) { // 參數(shù)類型 String

? ? ? ? ? ? return getBitmapFromPath(filePath); // 返回類型 Bitmap

? ? ? ? }

? ? })

? ? .subscribe(new Action1<Bitmap>() {

? ? ? ? @Override

? ? ? ? public void call(Bitmap bitmap) { // 參數(shù)類型 Bitmap

? ? ? ? ? ? showBitmap(bitmap);

? ? ? ? }

? ? });

FuncX 和 ActionX 的區(qū)別在 FuncX 包裝的是有返回值的方法暴备。

②:flatMap()? ? 一對多得轉(zhuǎn)化

場景:有個學生數(shù)組,打印出每個學生的中的所有課程

Student[] students = ...;

Subscriber<Course> subscriber = new Subscriber<Course>() {

? ? @Override

? ? public void onNext(Course course) {

? ? ? ? Log.d(tag, course.getName());

? ? }

? ? ...

};

Observable.from(students)

? ? .flatMap(new Func1<Student, Observable<Course>>() {

? ? ? ? @Override

? ? ? ? public Observable<Course> call(Student student) {

? ? ? ? ? ? return Observable.from(student.getCourses());

? ? ? ? }

? ? })

? ? .subscribe(subscriber);

③:doOnSubscribe()

Observable.create(onSubscribe)

? ? .subscribeOn(Schedulers.io())

? ? .doOnSubscribe(new Action0() {

? ? ? ? @Override

? ? ? ? public void call() {

? ? ? ? ? ? progressBar.setVisibility(View.VISIBLE); // 需要在主線程執(zhí)行

? ? ? ? }

? ? })

? ? .subscribeOn(AndroidSchedulers.mainThread()) // 指定主線程

? ? .observeOn(AndroidSchedulers.mainThread())

? ? .subscribe(subscriber);

在 doOnSubscribe()的后面跟一個 subscribeOn() 们豌,就能指定準備工作的線程了涯捻。

四、?使用場景

1望迎、 與 Retrofit 的結(jié)合

①:在操作User實體之前障癌,需要拿User進行比對數(shù)據(jù)

@GET("/user")

public Observable<User> getUser(@Query("userId") String userId);

getUser(userId)

? ? .doOnNext(new Action1<User>() {

? ? ? ? @Override

? ? ? ? public void call(User user) {

? ? ? ? ? ? processUser(user);

? ? ? ? })

? ? .observeOn(AndroidSchedulers.mainThread())

? ? .subscribe(new Observer<User>() {

? ? ? ? @Override

? ? ? ? public void onNext(User user) {

? ? ? ? ? ? userView.setUser(user);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onCompleted() {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onError(Throwable error) {

? ? ? ? ? ? // Error handling

? ? ? ? ? ? ...

? ? ? ? }

? ? });

②:假設(shè) /user 接口并不能直接訪問,而需要填入一個在線獲取的 token

@GET("/token")

public Observable<String> getToken();

@GET("/user")

public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId);

...

getToken()

? ? .flatMap(new Func1<String, Observable<User>>() {

? ? ? ? @Override

? ? ? ? public Observable<User> onNext(String token) {

? ? ? ? ? ? return getUser(token, userId);

? ? ? ? })

? ? .observeOn(AndroidSchedulers.mainThread())

? ? .subscribe(new Observer<User>() {

? ? ? ? @Override

? ? ? ? public void onNext(User user) {

? ? ? ? ? ? userView.setUser(user);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onCompleted() {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onError(Throwable error) {

? ? ? ? ? ? // Error handling

? ? ? ? ? ? ...

? ? ? ? }

? ? });

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末擂煞,一起剝皮案震驚了整個濱河市混弥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌对省,老刑警劉巖蝗拿,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蒿涎,居然都是意外死亡哀托,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門劳秋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仓手,“玉大人,你說我怎么就攤上這事玻淑∷悦埃” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵补履,是天一觀的道長添坊。 經(jīng)常有香客問我,道長箫锤,這世上最難降的妖魔是什么贬蛙? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮谚攒,結(jié)果婚禮上阳准,老公的妹妹穿的比我還像新娘。我一直安慰自己馏臭,他們只是感情好野蝇,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般绕沈。 火紅的嫁衣襯著肌膚如雪乱灵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天七冲,我揣著相機與錄音,去河邊找鬼规婆。 笑死澜躺,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的抒蚜。 我是一名探鬼主播掘鄙,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嗡髓!你這毒婦竟也來了操漠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤饿这,失蹤者是張志新(化名)和其女友劉穎浊伙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體长捧,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡嚣鄙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了串结。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哑子。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肌割,靈堂內(nèi)的尸體忽然破棺而出卧蜓,到底是詐尸還是另有隱情,我是刑警寧澤把敞,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布弥奸,位于F島的核電站,受9級特大地震影響先巴,放射性物質(zhì)發(fā)生泄漏其爵。R本人自食惡果不足惜布疙,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一队魏、第九天 我趴在偏房一處隱蔽的房頂上張望械筛。 院中可真熱鬧拢切,春花似錦猴凹、人聲如沸距糖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绰姻,卻和暖如春枉侧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狂芋。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工榨馁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帜矾。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓翼虫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親屡萤。 傳聞我的和親對象是個殘疾皇子珍剑,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

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

  • 轉(zhuǎn)一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong閱讀 910評論 0 2
  • 版權(quán)聲明:本文為小斑馬偉原創(chuàng)文章,轉(zhuǎn)載請注明出處死陆! 上篇簡單的闡述了響應(yīng)式編程的基本理論招拙。這篇主要對響應(yīng)編程進行詳...
    ZebraWei閱讀 2,263評論 0 2
  • 在正文開始之前的最后,放上GitHub鏈接和引入依賴的gradle代碼: Github: https://gith...
    蘇蘇說zz閱讀 677評論 0 2
  • 文章轉(zhuǎn)自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物線在正...
    xpengb閱讀 7,027評論 9 73
  • 今天早上起來發(fā)現(xiàn)食堂放假了措译,才意識到是5.1了…中午去食堂别凤,發(fā)現(xiàn)就只開了一家米飯一家粉。我已經(jīng)連續(xù)拉肚子5天了领虹,都...
    krysdracula閱讀 50評論 0 0