介紹
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)式編程");
? ? }
}