2018-01-09 RxJava、RxAndroid 學(xué)習(xí)

介紹

a library for composing asynchronous and event-based programs using observable sequences for the Java VM -------一個(gè)在 Java VM 上使用可觀測(cè)的序列來組成異步的、基于事件的程序的庫(kù)

使用

1、關(guān)聯(lián)

compile 'io.reactivex:rxjava:1.0.14'

compile 'io.reactivex:rxandroid:1.0.1'

2、簡(jiǎn)單示例

public void test01(){

? ? ? ? Log.e(tag,"------------test01-----------" +

? ? ? ? ? ? ? ? "\n----------簡(jiǎn)單實(shí)例01---------");

? ? ? ? //創(chuàng)建被觀察者

? ? ? ? Observable observable = Observable.create(new Observable.OnSubscribe() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Subscriber subscriber) {

? ? ? ? ? ? ? ? //調(diào)用觀察者的回調(diào)

? ? ? ? ? ? ? ? subscriber.onNext("我是");

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

? ? ? ? ? ? ? ? subscriber.onNext("簡(jiǎn)單示例");

? ? ? ? ? ? ? ? subscriber.onError(new Throwable("出錯(cuò)了"));

? ? ? ? ? ? ? ? subscriber.onCompleted();

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //創(chuàng)建觀察者

? ? ? ? Observer observer = new Observer() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onCompleted() {

? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");

? ? ? ? ? ? }

? ? ? ? ? ? @Override

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

? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onNext(String s) {

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

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? //注冊(cè),是的觀察者和被觀察者關(guān)聯(lián),將會(huì)觸發(fā)OnSubscribe.call方法

? ? ? ? observable.subscribe(observer);

? ? }

運(yùn)行結(jié)果:

? ? =====>: ------------test01-----------

? ? ? ? ? ? ----------簡(jiǎn)單實(shí)例01---------

? ? =====>: 我是

? ? =====>: RxJava

? ? =====>: 簡(jiǎn)單示例

? ? =====>: 出錯(cuò)了

Observable是被觀察者,通過create創(chuàng)建(還有其他方式,后面將會(huì)講到),傳入一個(gè)OnSubscribe對(duì)象,當(dāng)Observable調(diào)用subscribe進(jìn)行注冊(cè)觀察者時(shí),OnSubscribe的call方法會(huì)觸發(fā)。Observer是觀察者,他有三個(gè)回調(diào)方法:

onNext? ? ? :接受到一個(gè)事件

onCompleted :接受完事件后調(diào)用,只會(huì)調(diào)用一次

onError? ? :發(fā)生錯(cuò)誤時(shí)調(diào)用,并停止接受事件,調(diào)用一次

onCompleted和onError不會(huì)同時(shí)調(diào)用,只會(huì)調(diào)用其中之一

觀察者除了使用Observer,還可以使用Subscriber,它跟?Observer作用一樣,如下:

public void test02(){

? ? ? ? Log.e(tag,"------------test02-----------" +

? ? ? ? ? ? ? ? "\n----------簡(jiǎn)單實(shí)例02---------");

? ? ? ? //創(chuàng)建被觀察者

? ? ? ? Observable observable = Observable.create(new Observable.OnSubscribe() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Subscriber subscriber) {

? ? ? ? ? ? ? ? //調(diào)用觀察者的回調(diào)

? ? ? ? ? ? ? ? subscriber.onNext("我是");

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

? ? ? ? ? ? ? ? subscriber.onNext("簡(jiǎn)單示例");

? ? ? ? ? ? ? ? subscriber.onCompleted();

? ? ? ? ? ? ? ? subscriber.onError(new Throwable("出錯(cuò)了"));

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //創(chuàng)建觀察者

? ? ? ? Subscriber subscriber = new Subscriber() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onStart() {

? ? ? ? ? ? ? ? Log.e(tag,"onStart");

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onCompleted() {

? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");

? ? ? ? ? ? }

? ? ? ? ? ? @Override

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

? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onNext(String s) {

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

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? //注冊(cè),使得觀察者和被觀察者關(guān)聯(lián),將會(huì)觸發(fā)OnSubscribe.call方法

? ? ? ? observable.subscribe(subscriber);

? ? }

運(yùn)行結(jié)果

=====>: ------------test02-----------

? ? ? ? ----------簡(jiǎn)單實(shí)例02---------

=====>: onStart

=====>: 我是

=====>: RxJava

=====>: 簡(jiǎn)單示例

=====>: onCompleted

這里只是多了一個(gè)onStart方法 ,這個(gè)方法會(huì)在Observable調(diào)用方法subscribe注冊(cè)觀察者時(shí)調(diào)用一次,表明事件要開始了。

因?yàn)镾ubscriber只是對(duì)Observer的擴(kuò)展,用法都一樣,所以后面例子都用?Subscriber做觀察者。

3、Observable的創(chuàng)建

前面簡(jiǎn)單的例子中,創(chuàng)建Observable是通過create方法,當(dāng)然還有其他方法,體驗(yàn)一下吧:

public void test03(){

? ? ? ? Log.e(tag,"------------test03-----------" +

? ? ? ? ? ? ? ? "\n----------創(chuàng)建觀察者01---------");

? ? ? ? Integer[] ints={1,2,3,4};

? ? ? ? Observable.from(ints).subscribe(new Subscriber() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onCompleted() {

? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");

? ? ? ? ? ? }

? ? ? ? ? ? @Override

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

? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onNext(Integer integer) {

? ? ? ? ? ? ? ? Log.e(tag,integer+"");

? ? ? ? ? ? }

? ? ? ? });

? ? }

運(yùn)行結(jié)果

=====>: ------------test03-----------

? ? ? ? ----------創(chuàng)建觀察者01---------

=====>: 1

=====>: 2

=====>: 3

=====>: 4

=====>: onCompleted

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

public void test04(){

? ? ? ? Log.e(tag,"------------test04-----------" +

? ? ? ? ? ? ? ? "\n----------創(chuàng)建被觀察者02---------");

? ? ? ? Observable.just(1,2,3,4).subscribe(new Subscriber() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onCompleted() {

? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");

? ? ? ? ? ? }

? ? ? ? ? ? @Override

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

? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onNext(Integer integer) {

? ? ? ? ? ? ? ? Log.e(tag,integer+"");

? ? ? ? ? ? }

? ? ? ? });

? ? }

運(yùn)行結(jié)果

=====>: ------------test04-----------

? ? ? ? ----------創(chuàng)建被觀察者02---------

=====>: 1

=====>: 2

=====>: 3

=====>: 4

=====>: onCompleted

和from方法一樣,just(T...): 將傳入的參數(shù)依次發(fā)送出來。

4、觀察者的其他可用形式

觀察者Subscriber和Observer都需要寫三個(gè)回調(diào),有時(shí)候我們只關(guān)系其中一個(gè)回調(diào),或者兩個(gè)

public void test05(){

? ? ? ? Log.e(tag,"------------test05-----------" +

? ? ? ? ? ? ? ? "\n----------創(chuàng)建觀察者其他形式---------");

? ? ? ? String[] strs={"aa","bb","cc"};

? ? ? ? Action1 onNextAction = new Action1() {

? ? ? ? ? ? // onNext()

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? Action1 onErrorAction = new Action1() {

? ? ? ? ? ? // onError()

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Throwable throwable) {

? ? ? ? ? ? ? Log.e(tag,throwable.getMessage());

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? Action0 onCompletedAction = new Action0() {

? ? ? ? ? ? // onCompleted()

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call() {

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

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? Observable observable = Observable.from(strs);

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

? ? ? ? observable.subscribe(onNextAction);

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

? ? ? ? observable.subscribe(onNextAction, onErrorAction);

? ? ? // 自動(dòng)創(chuàng)建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 來定義 onNext()、 onError() 和 onCompleted()

? ? ? ? observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

? ? }

這里使用了Action1和Action0, Action0 是 RxJava 的一個(gè)接口,它只有一個(gè)方法 call(),這個(gè)方法是無參無返回值的;由于 onCompleted() 方法也是無參無返回值的,因此 Action0 可以被當(dāng)成一個(gè)包裝對(duì)象,將 onCompleted() 的內(nèi)容打包起來將自己作為一個(gè)參數(shù)傳入 subscribe() 以實(shí)現(xiàn)不完整定義的回調(diào)。 Action1 也是一個(gè)接口,它同樣只有一個(gè)方法 call(T param),這個(gè)方法也無返回值,但有一個(gè)參數(shù);與 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是單參數(shù)無返回值的,因此 Action1 可以將 onNext(obj) 和 onError(error) 打包起來傳入 subscribe() 以實(shí)現(xiàn)不完整定義的回調(diào)。事實(shí)上,雖然 Action0 和 Action1 在 API 中使用最廣泛,但 RxJava 是提供了多個(gè) ActionX 形式的接口 (例如 Action2, Action3) 的,它們可以被用以包裝不同的無返回值的方法。

5、線程調(diào)度

RxJava遵循線程不變?cè)瓌t,在不做特殊處理的情況下,在哪個(gè)線程調(diào)用 subscribe(),就在哪個(gè)線程生產(chǎn)事件;在哪個(gè)線程生產(chǎn)事件,就在哪個(gè)線程消費(fèi)事件。如果需要切換線程,就需要用到 Scheduler (調(diào)度器)

? ? public void test06(){

? ? ? ? Log.e(tag, "------------test06-----------" +

? ? ? ? ? ? ? ? "\n----------線程調(diào)度---------");

? ? ? ? //從網(wǎng)絡(luò)上根據(jù)用戶id,請(qǐng)求對(duì)應(yīng)用戶,并顯示用戶積分到界面

? ? ? ? Observable.create(new Observable.OnSubscribe() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Subscriber subscriber) {

? ? ? ? ? ? ? ? int id=111;

? ? ? ? ? ? ? ? UserInfo userinfo=getUserInfoFromNet(id);

? ? ? ? ? ? ? ? subscriber.onNext(userinfo.points);

? ? ? ? ? ? }

? ? ? ? }).subscribeOn(Schedulers.io())//事件產(chǎn)生在io線程

? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())//消耗事件在主線程

? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? public void call(Integer points) {

? ? ? ? ? ? ? ? ? Log.e(tag, "顯示用戶積分:" + points);

? ? ? ? ? ? ? }

? ? ? ? ? });

? ? }

? ? //模擬從網(wǎng)絡(luò)請(qǐng)求

? ? private UserInfo getUserInfoFromNet(int id) {

? ? ? ? UserInfo userInfo = new UserInfo();

? ? ? ? userInfo.points=100;

? ? ? ? return userInfo;

? ? }

? ? public class UserInfo{

? ? ? ? public int id;

? ? ? ? public int points;

? ? }

運(yùn)行結(jié)果

=====>: ------------test06-----------

? ? ? ? ----------線程調(diào)度---------

=====>: 顯示用戶積分:100

在io線程中根據(jù)id請(qǐng)求用戶信息,在主線程中將用戶積分顯示到界面

Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作,適用于復(fù)雜計(jì)算。

Schedulers.io(): I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)信息交互等)

AndroidSchedulers.mainThread(),它指定的操作將在 Android 主線程運(yùn)行

subscribeOn(): 指定 subscribe() 所發(fā)生的線程,即 Observable.OnSubscribe 被激活時(shí)所處的線程。或者叫做事件產(chǎn)生的線程。

observeOn(): 指定 Subscriber 所運(yùn)行在的線程。或者叫做事件消費(fèi)的線程

6、變換

舉一個(gè)例子:通過用戶id,從數(shù)據(jù)庫(kù)中請(qǐng)求用戶名稱,只需要名稱就行,id是int類型,用戶名稱是string類型

public void test07(){

? ? ? ? Log.e(tag, "------------test07-----------" +

? ? ? ? ? ? ? ? "\n----------變換01---------");

? ? ? ? //從數(shù)據(jù)庫(kù)中根據(jù)id獲取用戶名稱

? ? ? ? Observable.just(111)

? ? ? ? ? ? ? ? .map(new Func1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public String call(Integer id) {

? ? ? ? ? ? ? ? ? ? ? ? return getNameFromDb(id);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? }

? ? //模擬從數(shù)據(jù)獲取信息

? ? private String getNameFromDb(int id){

? ? ? ? return "username";

? ? }

? ? public class UserInfo{

? ? ? ? public int id;

? ? ? ? public String name;

? ? ? ? public int points;

? ? }

運(yùn)行結(jié)果

=====>: ------------test07-----------

? ? ? ? ----------變換01---------

=====>: username

這里的map有轉(zhuǎn)換的作用,這里是吧Observable轉(zhuǎn)換成了Observable,事件只能是一對(duì)一的轉(zhuǎn)換,把發(fā)射id的事件,轉(zhuǎn)換成了發(fā)射username的事件

flatmap轉(zhuǎn)換,舉一個(gè)例子:根據(jù)id從數(shù)據(jù)庫(kù)中獲取指定用戶的愛好,并打印出來

public void test08(){

? ? ? ? Log.e(tag, "------------test08-----------" +

? ? ? ? ? ? ? ? "\n----------變換02---------");

? ? ? ? Observable.just(111)

? ? ? ? ? ? ? ? .flatMap(new Func1>() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public Observable call(Integer id) {

? ? ? ? ? ? ? ? ? ? ? ? return Observable.from(getHobbies(id));

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? }

? ? //模擬從數(shù)據(jù)獲取信息

? ? private String[] getHobbies(int id){

? ? ? ? return new String[]{"singing","running","shopping"};

? ? }

? ? public class UserInfo{

? ? ? ? public int id;

? ? ? ? public String name;

? ? ? ? public int points;

? ? ? ? public String[] hobbies;

? ? }

運(yùn)行結(jié)果

=====>: ------------test08-----------

? ? ? ? ----------變換02---------

=====>: singing

=====>: running

=====>: shopping

這里將Observable轉(zhuǎn)換成了?Observable.from(getHobbies(id)),將發(fā)射id的事件,轉(zhuǎn)換成了多個(gè)發(fā)射愛好的事件(愛好有多個(gè)),事件是一對(duì)多

7、反注冊(cè)

rxJava是基于觀察者模式的,我們知道觀察者模式中有注冊(cè)和反注冊(cè),反注冊(cè)就是為了釋放資源,防止內(nèi)存泄露,rxjava中也是,我們也需要及時(shí)反注冊(cè)并釋放資源,

? ? private Subscription subscription;

? ? public void test09(){

? ? ? ? Log.e(tag, "------------test09-----------" +

? ? ? ? ? ? ? ? "\n----------反注冊(cè)---------");

? ? ? ? subscription = Observable.create(new Observable.OnSubscribe() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void call(Subscriber subscriber) {

? ? ? ? ? ? ? ? ? ? SystemClock.sleep(5000);\\暫停5秒鐘

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

? ? ? ? ? ? ? ? ? ? subscriber.onCompleted();\\標(biāo)志事件發(fā)送完畢,just和from會(huì)自動(dòng)調(diào)用onCompleted

? ? ? ? ? ? ? ? }

? ? ? ? ? ? })

? ? ? ? ? ? .subscribeOn(Schedulers.newThread())

? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())

? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? @Override

? ? protected void onDestroy() {

? ? ? ? super.onDestroy();

? ? ? ? Log.e(tag,"是否已經(jīng)反注冊(cè):"+subscription.isUnsubscribed()+"");

? ? ? ? //先判斷是否已經(jīng)反注冊(cè)

? ? ? ? if(!subscription.isUnsubscribed()){

? ? ? ? ? ? Log.e(tag,"進(jìn)行反注冊(cè)");

? ? ? ? ? ? subscription.unsubscribe();

? ? ? ? ? ? Log.e(tag,"是否已經(jīng)反注冊(cè):"+subscription.isUnsubscribed()+"");

? ? ? ? }

? ? }

Subscription是注冊(cè)關(guān)系,Observable調(diào)用subscribe方法時(shí),會(huì)形成一個(gè)注冊(cè)關(guān)系,Subscription的isUnsubscribed()方法來判斷是否已經(jīng)反注冊(cè),unsubscribe()方法來進(jìn)行反注冊(cè)。一般情況下,當(dāng)事件發(fā)送完成后,觀察者會(huì)自動(dòng)反注冊(cè),不用我們調(diào)用Subscription的unsubscribe()方法進(jìn)行反注冊(cè),但是當(dāng)有耗時(shí)操作時(shí),我們就有必要進(jìn)行反注冊(cè),上面代碼的運(yùn)行結(jié)果如下:

運(yùn)行結(jié)果

在事件還沒有發(fā)送完畢時(shí)(5秒之內(nèi)),我們關(guān)閉了activity:

=====>: ------------test09-----------

? ? ? ? ----------反注冊(cè)---------

=====>: 是否已經(jīng)反注冊(cè):false

=====>: 進(jìn)行反注冊(cè)

=====>: 是否已經(jīng)反注冊(cè):true

事件已經(jīng)發(fā)送完(5秒之后),我們關(guān)閉activity:

=====>: ------------test09-----------

? ? ? ? ----------反注冊(cè)---------

=====>: hahaha

=====>: 是否已經(jīng)反注冊(cè):true

8、操作符使用

rxJava有著豐富的操作符,來對(duì)數(shù)據(jù)進(jìn)行流式的操作處理,上面講到的map和flatmap就是rxJava的操作符,由于操作符太多,只示范常用的幾個(gè):

public void test10(){

? ? Log.e(tag, "------------test10-----------" +

? ? ? ? ? ? "\n----------操作符---------");

? String[] strs={"aa","bb","bb","cc","dd","ee"};

? ? Observable observable = Observable.from(strs);

? ? //filter(Func1)方法來過濾我們觀測(cè)序列中不想要的值

? ? //take(count)方法來限制獲取多少個(gè)數(shù)據(jù)

? ? Log.e(tag,"---------filter & take----------");

? ? observable

? ? ? ? ? ? .filter(new Func1() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public Boolean call(String s) {

? ? ? ? ? ? ? ? ? ? //把已b結(jié)尾的數(shù)據(jù)去掉

? ? ? ? ? ? ? ? ? ? return !s.endsWith("b");

? ? ? ? ? ? ? ? }

? ? ? ? ? ? })

? ? ? ? ? ? .take(3)//取3個(gè)數(shù)據(jù)

? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? ? ? }

? ? ? ? });

? ? Log.e(tag,"---------skip & first----------");

? ? observable

? ? ? ? ? ? .skip(3)

? ? ? ? ? ? .first()

? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void call(String s) {

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

? ? ? ? ? ? ? ? }

? ? ? ? ? ? });

}

運(yùn)行結(jié)果

=====>: ------------test10-----------

? ? ? ? ----------操作符---------

=====>: ---------filter & take----------

=====>: aa

=====>: cc

=====>: dd

=====>: ---------skip & first----------

=====>: cc

類似的這種簡(jiǎn)單的操作符還有:

last() 取最后一個(gè)

distinct() 去除重復(fù)的

skipLast() 去除最后一個(gè)

takeLast(count) 取最后count個(gè)

limit(count) 限制個(gè)數(shù)

doOnNext(Action1) 允許我們?cè)诿看屋敵鲆粋€(gè)元素之前做一些額外的事情,比如保存起來。

還有好多,這只是簡(jiǎn)單的介紹一下,在RxJava操作符專題中有詳解

9、RxLifecycle

我們上面提到了反注冊(cè)來防止內(nèi)存泄露,但是反注冊(cè)需要我們自己動(dòng)手寫,而使用Rxlifecycle就可以幫助我們將反注冊(cè)綁定到activity或者fragment的生命周期中,在他們的生命周期中自動(dòng)去解綁。

使用方法

添加依賴,有最新的依賴,但是下面的比較穩(wěn)定編譯也能通過

compile 'com.trello:rxlifecycle:0.3.1'

compile 'com.trello:rxlifecycle-components:0.3.1'

Activity/Fragment需繼承RxAppCompatActivity/RxFragment,目前支持的有RxAppCompatActivity、RxFragment、RxDialogFragment、RxFragmentActivity

綁定生命周期的時(shí)候可調(diào)用的方法:

bindToLifecycle()

bindUntilEvent()

例子

public class MainActivity extends RxAppCompatActivity {

? ? private static final String TAG = "=====>";

? ? @Override

? ? protected void onCreate(Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? Log.e(TAG, "onCreate()");

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? Observable.interval(1, TimeUnit.SECONDS)

? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call() {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onCreate()");

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .compose(this.bindUntilEvent(ActivityEvent.PAUSE))

? ? ? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(Long num) {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onCreate(), running until onPause(): " + num);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? }

? ? @Override

? ? protected void onStart() {

? ? ? ? super.onStart();

? ? ? ? Log.e(TAG, "onStart()");

? ? ? ? // Using automatic unsubscription, this should determine that the correct time to

? ? ? ? // unsubscribe is onStop (the opposite of onStart).

? ? ? ? Observable.interval(1, TimeUnit.SECONDS)

? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call() {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onStart()");

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .compose(this.bindToLifecycle())

? ? ? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(Long num) {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onStart(), running until in onStop(): " + num);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? }

? ? @Override

? ? protected void onResume() {

? ? ? ? super.onResume();

? ? ? ? Log.e(TAG, "onResume()");

? ? ? ? // `this.` is necessary if you're compiling on JDK7 or below.

? ? ? ? //

? ? ? ? // If you're using JDK8+, then you can safely remove it.

? ? ? ? Observable.interval(1, TimeUnit.SECONDS)

? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call() {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onResume()");

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .compose(this.bindUntilEvent(ActivityEvent.DESTROY))

? ? ? ? ? ? ? ? .subscribe(new Action1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(Long num) {

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onResume(), running until in onDestroy(): " + num);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? }

? ? @Override

? ? protected void onPause() {

? ? ? ? super.onPause();

? ? ? ? Log.e(TAG, "onPause()");

? ? }

? ? @Override

? ? protected void onStop() {

? ? ? ? super.onStop();

? ? ? ? Log.e(TAG, "onStop()");

? ? }

? ? @Override

? ? protected void onDestroy() {

? ? ? ? super.onDestroy();

? ? ? ? Log.e(TAG, "onDestroy()");

? ? }

}

打開activity,兩秒后關(guān)閉,這樣每一個(gè)Observable發(fā)送兩個(gè)事件

運(yùn)行結(jié)果

=====>: onCreate()

=====>: onStart()

=====>: onResume()

=====>: Started in onCreate(), running until onPause(): 0

=====>: Started in onStart(), running until in onStop(): 0

=====>: Started in onResume(), running until in onDestroy(): 0

=====>: Started in onCreate(), running until onPause(): 1

=====>: Started in onStart(), running until in onStop(): 1

=====>: Started in onResume(), running until in onDestroy(): 1

=====>: Unsubscribing subscription from onCreate()

=====>: onPause()

=====>: Unsubscribing subscription from onStart()

=====>: onStop()

=====>: Unsubscribing subscription from onResume()

關(guān)閉activity后,可以看出每一個(gè)Observable對(duì)應(yīng)的注冊(cè)者在相應(yīng)的生命周期函數(shù)中反注冊(cè)。?bindUntilEvent()方法需要傳入要綁定的生命周期。使用ActivityEvent類,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分別對(duì)應(yīng)生命周期內(nèi)的方法。使用bindUntilEvent指定在哪個(gè)生命周期方法調(diào)用時(shí)取消訂閱

bindToLifecycle()方法完成Observable發(fā)布的事件和當(dāng)前的組件綁定,實(shí)現(xiàn)生命周期同步。從而實(shí)現(xiàn)當(dāng)前組件生命周期結(jié)束時(shí),自動(dòng)取消對(duì)Observable訂閱。

10、RxBinding

RxBinding是Rx中處理控件異步調(diào)用的方式, 也是由Square公司開發(fā), Jake負(fù)責(zé)編寫. 通過綁定組件, 異步獲取事件, 并進(jìn)行處理。

使用

關(guān)聯(lián)

compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'

compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0'

實(shí)例


? ? xmlns:tools="http://schemas.android.com/tools"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent"

? ? android:paddingBottom="@dimen/activity_vertical_margin"

? ? android:paddingLeft="@dimen/activity_horizontal_margin"

? ? android:paddingRight="@dimen/activity_horizontal_margin"

? ? android:paddingTop="@dimen/activity_vertical_margin"

? ? android:orientation="vertical"

? ? tools:context="cn.domob.android.rxjava_android.MainActivity">


? ? ? ? android:id="@+id/tv_main"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:text="Hello World!" />


? ? ? ? android:id="@+id/bt_main_01"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:text="改變字體顏色"/>


? ? ? ? android:id="@+id/bt_main_02"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:text="長(zhǎng)按彈toast"/>


? ? ? ? android:id="@+id/et_main"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:hint="搜索"/>


? ? ? ? android:id="@+id/lv_main"

? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="match_parent"/>

public class MainActivity extends RxAppCompatActivity {

? ? private static final String TAG = "=====>";

? ? @InjectView(R.id.tv_main)

? ? TextView tv;

? ? @InjectView(R.id.bt_main_01)

? ? Button bt01;

? ? @InjectView(R.id.bt_main_02)

? ? Button bt02;

? ? @InjectView(R.id.et_main)

? ? EditText et;

? ? @InjectView(R.id.lv_main)

? ? ListView lv;

? ? @Override

? ? protected void onCreate(Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activity_main);

? ? ? ? ButterKnife.inject(this);

? ? ? ? //單機(jī)事件

? ? ? ? RxView.clicks(bt01).subscribe(new Action1() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Void aVoid) {

? ? ? ? ? ? ? ? tv.setTextColor(Color.parseColor("#ff0000"));

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //長(zhǎng)按事件

? ? ? ? RxView.longClicks(bt02).subscribe(new Action1() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Void aVoid) {

? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "hahha", Toast.LENGTH_SHORT).show();? ?

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //防止連續(xù)點(diǎn)擊

? ? ? ? RxView.clicks(bt02).throttleFirst(5, TimeUnit.SECONDS).subscribe(new Action1() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Void aVoid) {

? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "防止多次連續(xù)點(diǎn)擊", Toast.LENGTH_SHORT).show();

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? //完成關(guān)鍵詞聯(lián)想功能,debounce()在一定的時(shí)間內(nèi)沒有操作就會(huì)發(fā)送事件,顯示關(guān)鍵詞

? ? ? ? final ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_expandable_list_item_1);

? ? ? ? lv.setAdapter(adapter);

? ? ? ? RxTextView.textChanges(et)

? ? ? ? ? ? ? ? .debounce(600,TimeUnit.MILLISECONDS)

? ? ? ? ? ? ? ? .map(new Func1() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public String call(CharSequence charSequence) {

? ? ? ? ? ? ? ? ? ? ? ? return charSequence.toString();

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .map(new Func1>() {

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public List call(String key) {

? ? ? ? ? ? ? ? ? ? ? ? ArrayList arrayList = new ArrayList<>();

? ? ? ? ? ? ? ? ? ? ? ? if(!TextUtils.isEmpty(key)){

? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < getdata().size(); i++) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(getdata().get(i).contains(key))

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? arrayList.add(getdata().get(i));

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? return arrayList;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())

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

? ? ? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? ? ? public void call(List strings) {

? ? ? ? ? ? ? ? ? ? ? ? adapter.clear();

? ? ? ? ? ? ? ? ? ? ? ? adapter.addAll(strings);

? ? ? ? ? ? ? ? ? ? ? ? adapter.notifyDataSetChanged();

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? });

? ? ? ? RxAdapterView.itemClicks(lv).subscribe(new Action1() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void call(Integer integer) {

? ? ? ? ? ? ? ? et.setText(adapter.getItem(integer));

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? public List getdata(){

? ? ? ? return Arrays.asList("abc","abddfds","123","124567","1278934","adfghjl","!@#45d","響應(yīng)式編程");

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,697評(píng)論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,182評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,406評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,772評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,973評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評(píng)論 1 285
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,644評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,953評(píng)論 2 373

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

  • 注:只包含標(biāo)準(zhǔn)包中的操作符,用于個(gè)人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,210評(píng)論 2 8
  • 我從去年開始使用 RxJava ,到現(xiàn)在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,546評(píng)論 7 62
  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符。對(duì)于擴(kuò)展包,由于使用率較低,如有需求,請(qǐng)讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 45,738評(píng)論 8 93
  • 文章轉(zhuǎn)自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物線在正...
    xpengb閱讀 7,054評(píng)論 9 73
  • 看過三國(guó)演義的人都對(duì)一個(gè)人印象深刻,那個(gè)人就是呂蒙。不僅是因?yàn)閰蚊汕軞⒘岁P(guān)羽,更是因?yàn)閰蚊赏瓿闪宋覀兒芏嗳艘惠呑佣?..
    書暢閱讀 1,105評(píng)論 0 3