在看本文之前,假如你已經看過一些Rxjava的介紹,有了大致瞭解,但是仍然看不懂RxJava代碼,並且對它的使用場景心存疑惑,那麼本篇文章是適合你的。
RxJava的學習還是有一定門檻的,難度在於理解它的思維方式,和各種操作符的用處。本篇文章從最基礎的RxJava示例來講解,說明RxJava的基本使用及基礎操作符的作用。
注:本篇文章的RxJava,指的是RxJava1,其他版本的操作符和用法可能會有一些變化。
本篇目錄
- 前言:RxJava的一些介紹
- 得到Observable被觀察者對象
- 得到Observer觀察者對象
- 實現觀察訂閱
- RxJava實例講解
- Retrofit+RxJava用法示例
前言:RxJava的一些介紹
首先要了解,RxJava是基於觀察者模式的,簡而言之就是觀察者訂閱了被觀察者,然後被觀察者產生的數據變化會通知到觀察者,觀察者從而作出反應。這裏就不多做講解了。在Android裏,觀察者模式的場景非常多,比如OnClickListener,比如EventBus等。
那麼RxJava能幹嘛呢?對入門來說,只要是“拿數據,做處理”這樣的流程,都可以用RxJava實現。比如Retrofit網絡請求經常搭配RxJava來實現。甚至打印一個字符串列表也可以用RxJava實現,只要你不嫌它大材小用。
在RxJava裏,觀察者用Observer類或者Subscriber類表示,其中後者是前者的實現類,兩者用法基本相同。觀察者就是處理數據的角色。
而被觀察者用Observable類表示,它是產生數據的角色。
一、首先我們來看下如何得到一個Observable對象,也就是被觀察者。
得到Observable有下面幾種常用方法:
1.Observable.create(xxx)
這裏的xxx爲Observable.OnSubscribe對象,即訂閱事件發生的時候,用於產生數據的對象。
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("1.....");
subscriber.onNext("2.....");
subscriber.onNext("3.....");
subscriber.onCompleted();
}
});
這個數據源產生的數據,就是三個字符串。
2.Observable.from(yyy)
這裏的yyy爲數組,集合,或者Future對象
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("444444444");
Observable observable = Observable.from(list);
同樣,這個observable對象所能產生的數據也是四個字符串。
3.Observable.just(x,y,z…)
這裏的x,y,z…可以是不同類型的數據。
Observable observable = Observable.just(1,2,3,4,5);
上例這個observable能產生1~5的數字。
二、再來看下如何得到一個觀察者對象(Subscriber或者Observer)
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
};
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
};
上面實現了兩種觀察者對象,Subscriber和Observer對象所要實現的抽象方法是一樣的。
這裏我們定義此觀察者處理的數據類型爲String類型。實際可根據需求來。按上面這樣得到的觀察者對象,能做什麼呢?
onNext(String s):用於處理數據。
onCompleted():數據全部處理完成,會走到這裏。
onError(Throwable e):數據處理過程出錯,會走這裏。
三、實現訂閱
上面兩步已經得到了被觀察者和觀察者對象,還差一步,就是確立訂閱關係:
observable.subscribe(observer);
或者
observable.subscribe(subscriber);
看上面這兩行代碼會發現,在RxJava裏,訂閱關係是被觀察者(observable)訂閱了觀察者(observer),與我們平時的理解相反。
其實Rxjava這麼寫只是爲了鏈式調用比較方便。真正subscribe()方法的源碼實現裏,仍然是觀察者訂閱了被觀察者。
實際使用中,還可以通過observable.subscribe(new Action0(){…})這樣的方式,即不必定義觀察者,而是通過Action0這樣的類包裝得到。下面會有例子。
四、實例解析
把上面三步用鏈式調用連接起來,完整的例子如下:
例1:打印字符串基本示例
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("str1");
subscriber.onNext("str2");
subscriber.onNext("str3");
subscriber.onCompleted();
}
}).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Log.d("test", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("test", "onError");
}
@Override
public void onNext(String s) {
Log.d("test", "onNext:"+s);
}
});
運行結果:
D/test: onNext:str1
D/test: onNext:str2
D/test: onNext:str3
D/test: onCompleted
這個例子實現的功能很簡單,就是依次打印三個字符串,完成後再打印"onCompleted"。如果流程中出了錯誤,則會打印"onError"。
例2:流程前後加入額外處理的示例
subscribe()方法傳入的可以是Subscriber對象,Observer對象,或者Action1對象。
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("test", "call:"+s);
}
});
同樣功能很簡單,就是依次打印四個字符串。
如果想在打印前後做一些額外處理,怎麼辦呢?可以像下面這樣改:
List<String> list=new ArrayList<>();
list.add("11111");
list.add("22222");
list.add("33333");
list.add("44444");
Observable.from(list)
//處理前的操作
.doOnSubscribe(new Action0() {
@Override
public void call() {
Log.d("test", "doOnSubscribe");
}
})
//處理完成後的操作
.doOnCompleted(new Action0() {
@Override
public void call() {
Log.d("test", "doOnCompleted");
}
})
//正式處理的操作
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("test", "call:"+s);
}
});
上面加上了doOnSubscribe和doOnCompleted操作,用於在正式處理前後進行額外處理。
類似地,在流程發生錯誤,或者終止等時機,RxJava都有對應的方法用於處理。
還可以看到,上面出現了Action0和Action1兩個類,它們有什麼區別呢?
Action0的call()不會傳入參數,而Action1的call()會傳入一個參數。類似地還有Action2,Action3,Action4等等。
運行結果:
D/test: doOnSubscribe
D/test: call:11111
D/test: call:22222
D/test: call:33333
D/test: call:44444
D/test: doOnCompleted
例3:數據處理前的篩選變換
Observable.just(1,2,3,4,5)
.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer%2==0;
}
})
.subscribe(integer -> Log.d("test", "call:"+integer));
這裏有個操作符filter,顧名思義是用來篩選數據的。而Func1這個類,用於實現具體的處理邏輯,它和Action1這個類的不同點在於有返回值。
這個例子的功能是篩選出能被2整除的數字,運行結果如下:
D/test: call:2
D/test: call:4
再看一個常用操作符,map:
Observable.just(1,2,3,4,5)
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer*2;
}
})
.subscribe(integer -> Log.d("test", "call:"+integer));
map操作符的作用是對數據進行統一的處理。在本例中是對各個數字乘以2。
運行結果如下:
D/test: call:2
D/test: call:4
D/test: call:6
D/test: call:8
D/test: call:10
還有其它各種處理數據的操作符,如得到數據的前幾位,後幾位,排序等。你能想到的各種常用處理,RxJava基本都有對應的操作符。
另外這個例子中使用了lambda表達式,簡化了代碼。
例4:線程的切換示例
使用RxJava可以很方便地進行線程切換,每一步操作都可以切換線程。如下例:
Observable.just(1, 2, 3, 4) // IO 線程,由第一個 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新線程,由上一行的 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 線程,由由上一行的 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主線程,由由上一行的 observeOn() 指定
切換線程可以使用subscribeOn和observeOn兩個操作符。這兩個有什麼區別呢?
subscribeOn傳入的的是被觀察者,即數據源產生數據時所在的線程。
observeOn傳入的是處理數據所在的線程。
如果鏈式調用中,出現了多個subscribeOn,則數據源產生數據的線程是首個subscribeOn指定的線程。
而每調一次observeOn傳入不同的線程,下一步的數據操作就會變到該線程裏。
可參考扔物線的RxJava講解。
五、最後,貼上Retrofit+RxJava使用示例:
service.login(phone, password)//獲取Observable對象
.subscribeOn(Schedulers.newThread())// 定義登錄操作(獲取Observable對象)在新的線程進行
.observeOn(Schedulers.io())//請求完成後在io線程中執行保存用戶信息
.doOnNext(new Action1<UserInfo>() {
@Override
public void call(UserInfo userInfo) {
saveUserInfo(userInfo);//保存用戶信息到數據庫
}
})
.observeOn(AndroidSchedulers.mainThread())//最後在主線程中執行
.subscribe(new Subscriber<UserInfo>() {
@Override
public void onCompleted() {
//操作完成
}
@Override
public void onError(Throwable e) {
//請求失敗
}
@Override
public void onNext(UserInfo userInfo) {
//請求成功,顯示用戶信息,在主線程
showUserInfo();
}
});