學習RxJava,做一下筆記
筆記:RxJava(二)
1、描述
RxJava
是一個基于事件流的實現異步操作的庫,類似Android
的handler、AsyncTask
- 隨著程序邏輯變得越來越復雜,它依然能夠保持簡潔
RxJava
的異步實現,是通過一種擴展的觀察者模式來實現的- 觀察模式可實現回調,采用訂閱
Subscribe
的方式將被觀察者Observable
與觀察者Observer
鏈在一起,實現訂閱關系,進行消息事件的通知
2、依賴地址
- RxJava在github的地址 https://github.com/ReactiveX/RxJava
現在官網的最新版本就是v 2.1.13 - RxAndroid在github的地址 https://github.com/ReactiveX/RxAndroid
現在官網的最新版本就是v 2.0.2
3、簡單創建用法與理解
3.1、Observable.create(ObservsbleOnSubscribe)的使用
/**
* 一、創建 可觀察者(Observable ) 以及 生產事件
*
*
* 1. 創建可觀察者 Observable 對象,可觀察的數據類型為String
* 2.create() 是 RxJava 最基本的創造事件序列的方法,還有just(多個數據)、from(數據數組)等
* 3.create(ObservableOnSubscribe)此處一個ObservableOnSubscribe對象參數
* 4.當 Observable 被訂閱時,OnSubscribe 的 call() 方法會自動被調用,即事件序列就會依照設定依次被觸發
* 也就是只有被訂閱時,事件才會發送
*/
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
/**
* 1.重寫的subscribe(),自定義需要發送的事件
* 2. 通過 ObservableEmitter類對象,事件發射器,產生事件并通知觀察者
*/
emitter.onNext("test1");
emitter.onNext("test2");
emitter.onNext("test3");
emitter.onNext("test4");
emitter.onComplete();
//=====================================>>>>>>>>>>關注①
//emitter.onNext("test1");
//emitter.onNext("test2");
//emitter.onNext("test3");
//emitter.onComplete();
//emitter.onNext("test4");
// =====================================>>>>>>>>>>關注②
// emitter.onNext("test1");
// emitter.onNext("test2");
// emitter.onError(new Throwable("onError"));
// emitter.onNext("test3");
// emitter.onComplete();
// emitter.onNext("test4");
}
});
/**
*
* 二、創建 觀察者 (Observer )以及 自定義響應事件的行為
*
*
* 1. 創建觀察者 (Observer )對象,觀察數據對象為String
* 2. 自動復寫對應事件的方法 從而 響應對應的事件
*
*
*/
Observer<String> observer=new Observer<String>() {
// 觀察者接收事件之前,默認最先調用復寫 onSubscribe()這個方法
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.d("TAG", "開始subscribe連接,接收上游可觀察者(Observable)的事件");
}
/**
* 當可觀察者生產Next事件 這里的 觀察者接收到時,會調用該復寫這個方法 進行事件響應,可接收多個Next事件,
* 直到接收到上游可觀察者onComplete/onError事件,其中onComplete/onError事件是唯一的,兩者之間是互斥的
*/
@Override
public void onNext(@NonNull String s) {
Log.d("TAG", "接收到Next事件=="+s);
}
/**
* 當可觀察者生產Error事件并且 觀察者接收到時,會調用該復寫這個方法 進行響應
* 當觀察者接收到可觀察者發過來的onError事件時,觀察者不再接收事件了,但 可觀察者可以繼續發送事件
* onError事件與onComplete事件時互斥的,兩者只能有其一
*/
@Override
public void onError(@NonNull Throwable e) {
Log.d("TAG", "接收到onError事件=="+e.toString());
}
// 當被觀察者生產Complete事件& 觀察者接收到時,會調用該復寫方法 進行響應
@Override
public void onComplete() {
Log.d("TAG", "接收到onComplete事件");
}
};
/**
*
* 三、通過訂閱(Subscribe)連接觀察者和被觀察者
*
* 就好比可觀察者為上游的出水水管,觀察者為下游接水水管,中間通過Subscribe連接,水就可以通了
* 此時事件可產生,發射,接收
*/
observable.subscribe(observer);
打印的log如下圖
關注① 當接收到了onComplete事件后,接收者Observer不再接收后面的事件,但可觀察者Observable依然會發射事件
打印log結果
關注② 當接收到了onError事件后,接收者Observer不再接收后面的事件,但可觀察者Observable依然會發射事件
3.1.1、RxJava的基于事件流的鏈式使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("test1");
emitter.onNext("test2");
emitter.onNext("test3");
emitter.onComplete();
emitter.onError(new Throwable("onError"));
emitter.onNext("test4");
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
//====================================>>>>>>>>>>>關注③
Log.e("TAG", "開始subscribe連接,接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull String s) {
Log.e("TAG", "接收到Next事件==" + s);
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
}
}
打印log結果:接收了 test1、test2、test3和onComplete事件
關注③ 可采用 Disposable.dispose() 切斷觀察者 與 被觀察者 之間的連接
public class MainActivity extends AppCompatActivity {
// 定義Disposable類變量
private Disposable mDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("test1");
emitter.onNext("test2");
emitter.onNext("test3");
emitter.onNext("test4");
emitter.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
// 對Disposable類變量賦值
mDisposable=d;
Log.e("TAG", "開始接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull String s) {
Log.e("TAG", "接收到Next事件==" + s);
/**
* 當接收的事件為test2的時候,切斷觀察者 與 可觀察者 之間的連接
* 即觀察者 不再繼續 接收 可觀察者發送的事件,但可觀察者還是可以繼續發送事件
*
* 就好比可觀察者為上游的出水水管,觀察者為下游接水水管,中間通過Subscribe連接,現在將兩個水管的交接出去掉
* 下游不再可以接收水,上游卻可以繼續出水
*/
if (s.equals("test2")){
mDisposable.dispose();
}
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
}
}
Log打印結果:下圖可看出,當接收的事件為test2事件后,觀察者不再接收后面的事件,連onComplete事件也不再接收,但此時,可觀察者依然在繼續發送事件
3.2、RxJava
其他簡單創建用法
3.2.1、just(Object)
的使用
1、快速的創建可觀察者對象
2、直接發送 傳入的事件(參數)轉化為Observable
對象
3、最多只能發送10個參數
4、將傳入的參數依次發射出來
5、與fromXxx( T[] ) / fromXxx( Iterable<? extends T> )
用法很接近,參數前者是一個一個
的,后者是數組T[]
的形式 /Iterable
拆分成的具體對象
6、不那么準確的說fromArray( T[] )
是just(Object)
的加強版
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Observable
.just("test1","test2","test3","test4","test5","test6","test7","test8","test9","test10")
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("TAG", "開始接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull String s) {
Log.e("TAG", "接收到Next事件==" + s);
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
}
}
log打印結果:
3.2.2、fromArray( T [ ] )的簡單使用
1、 可發送10個以上事件(數組形式)
2、不那么準確的說fromArray( T[] )
是just(Object)
的加強版
3、與fromXxx( T[] ) / fromXxx( Iterable<? extends T> )
用法很接近
4、與fromIterable( list )
用法很接近
5、fromArray( T[] )
的參數是一個數組,將數組中的數據轉換為一個個Observable對象
6、若傳入一個list集合,會直接把list當做一個數據元素,轉換為Observable對象發送出去,示例看關注④
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 設置需要傳入的數組
* 快速創建Observable對象
*/
String[] items = {"test1","test2","test3","test4","test5","test6","test7","test8","test9","test10"};
Observable
.fromArray(items)
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("TAG", "開始接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull String s) {
Log.e("TAG", "接收到Next事件==" + s.toString());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
log打印結果 :
關注④
fromArray()
傳入一級list集合,會將這個集合轉換為一個
Observable對象
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 設置需要傳入的數組
* 快速創建Observable對象
*/
String[] items = {"test1","test2","test3","test4","test5","test6","test7","test8","test9","test10"};
List<String> list=new ArrayList<>();
for (String item:items){
list.add(item);
}
Observable
.fromArray(list)
.subscribe(new Observer<List>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("TAG", "開始接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull List s) {
Log.e("TAG", "接收到Next事件==" + s.toString());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
下面是參數為 數組
與參數為 list
的log打印結果:
3.2.2.1、額外說明:此處參考文章來自---------Android Rxjava:這是一篇 清晰 & 易懂的Rxjava 入門教程
public final Disposable subscribe() {}
// 表示觀察者不對被觀察者發送的事件作出任何響應(但可觀察者還是可以繼續發送事件)
public final Disposable subscribe(Consumer<? super T> onNext) {}
// 表示觀察者只對被觀察者發送的Next事件作出響應
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {}
// 表示觀察者只對被觀察者發送的Next事件 & Error事件作出響應
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
// 表示觀察者只對被觀察者發送的Next事件、Error事件 & Complete事件作出響應
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
// 表示觀察者只對被觀察者發送的Next事件、Error事件 、Complete事件 & onSubscribe事件作出響應
public final void subscribe(Observer<? super T> observer) {}
// 表示觀察者對被觀察者發送的任何事件都作出響應
3.2.3、fromIterable( list )
的簡單使用
與前面幾個類似,參數是集合list,用法跟前面幾個一樣,這里就不說明了,需要的話就看前面幾個的說明
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 設置需要傳入的數組
* 快速創建Observable對象
*/
String[] items = {"test1","test2","test3","test4","test5","test6","test7","test8","test9","test10"};
List<String> list=new ArrayList<>();
for (String item:items){
list.add(item);
}
Observable
.fromIterable(list)
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("TAG", "開始接收上游可觀察者(Observable)的事件");
}
@Override
public void onNext(@NonNull String s) {
Log.e("TAG", "接收到Next事件==" + s);
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("TAG", "接收到onError事件==" + e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
log打印結果:
3.3、defer()
的簡單使用
1、在經過了x秒后,需要自動執行y操作
2、每隔x秒后,需要自動執行y操作
3.4、timer()
的簡單使用
1、延遲指定時間后,發送1個數值0
(Long類型)
2、原理:延遲指定時間后,調用一次onNext(0)
3、發送一個0,一般用于檢測
4、timer操作符默認運行在一個新線程上,既然可以默認也可以自定義,timer(long,TimeUnit,Scheduler)
第三個參數可自定義線程,指定timer的運行線程
// 延遲1s后,發送一個long類型數值
Observable.timer(1, TimeUnit.SECONDS)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "開始連接");
}
@Override
public void onNext(Long value) {
Log.e("TAG", "onNext=="+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收到onError事件");
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
log打印結果:先是打印 開始連接
,1s后,再打印onNext==0 接收到onComplete事件
3.5、interval()
的簡單使用
1、快速創建1個被觀察者對象(
Observable
)
2、每隔指定時間 就發送 事件
3、發送的事件序列 = 從0開始、無限遞增1的的整數序列
/**
*
* 延遲3s后發送事件,每隔1秒產生1個數字(從0開始遞增1,無限個)
*
*
* 參數1 = 第1次延遲時間;
* 參數2 = 間隔時間數字;
* 參數3 = 時間單位;
*/
Observable.interval(3,1,TimeUnit.SECONDS)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "開始連接");
}
// 默認最先調用復寫的 onSubscribe()
@Override
public void onNext(Long value) {
Log.e("TAG", "接收onNext事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收onError事件"+e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收onComplete事件");
}
});
log打印結果:第一次打印開始連接
,3s后,打印 接收onNext事件0
, 之后每隔一秒打印一個接收onNext事件1........N
無限遞增
3.6、intervalRange()
的簡單使用
1、快速創建1個被觀察者對象(
Observable
)
2、每隔指定時間 就發送 事件,可指定發送的數據的數量
3、發送的事件序列 = 從0開始、遞增1的的整數序列
4、. 作用類似于interval()
,但可指定發送的數據的數量
/**
* 從3開始,一共發送10個事件,第1次延遲2s發送,之后每隔2秒產生1個數字
*
*
* 參數1 = 事件序列起始點
* 參數2 = 事件數量
* 參數3 = 第1次事件延遲發送時間
* 參數4 = 間隔時間數字
* 參數5 = 時間單位
*/
Observable.intervalRange(3,10,2, 1, TimeUnit.SECONDS)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", " 開始連接");
}
@Override
public void onNext(Long value) {
Log.e("TAG", " 接收onNext事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", " 接收onError事件"+e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", " 接收onComplete事件");
}
});
3.7、range()
的簡單使用
1、快速創建1個被觀察者對象(
Observable
)
2、連續發送 1個事件序列,可指定范圍
3、發送的事件序列 = 從0開始、遞增1的的整數序列
4、作用類似于intervalRange()
,但區別在于:無延遲發送事件
/**
* 從4開始發送,每次發送事件遞增1,一共發送5個事件
*
* 參數1 = 事件序列起始點
* 參數2 = 事件數量
* 注:若設置為負數,則會拋出異常
*/
Observable.range(4,5)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "開始連接");
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收onError事件"+e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收onComplete事件");
}
});
log打印結果:
4、RXJava常用操作符的簡單使用*
4.1、變換操作符
①、
map()
將事件序列中的對象或整個序列進行加工轉換,將可觀察者要發送的事件轉換為任意的類型事件。
②、Flatmap()
③、ConcatMap()
④、Buffer()
4.1.1、Map()
簡單使用
1、說明: 將事件序列中的對象或整個序列進行加工處理,轉換成不同的事件或事件序列,不準確的說,就是
傳進去的值
被轉換了,返回的返回值
不同了,將可觀察者要發送的事件轉換為任意的類型事件。
Observable.create(new ObservableOnSubscribe<Integer>() {
// 可觀察者發送事件 = 參數為整型 = 1、2、3
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
})
// 使用Map變換操作符中的Function函數對可觀察者發送的事件
// 進行統一變換:將整型變換成字符串類型
.map(new Function<Integer, String>() {
@Override
public String apply(@NonNull Integer integer) throws Exception {
return "使用 Map變換操作符 將事件" + integer +"的參數從 整型"
+integer + " 變換成 字符串類型" + integer ;
}
})
.subscribe(new Consumer<String>() {
// 觀察者接收事件時,是接收到變換后的事件 = 字符串類型
@Override
public void accept(String s) throws Exception {
Log.e("TAG", s);
}
});
log打印結果:
4.1.2、FlatMap()
簡單使用
- 將被觀察者發送的事件序列進行 拆分 & 單獨轉換,再合并成一個新的事件序列,最后再進行發送
- 無序的將被觀察者發送的整個事件序列進行變換
// 采用RxJava基于事件流的鏈式操作
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
}
// 采用flatMap()變換操作符
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
// final List<String> list = new ArrayList<>();
// for (int i = 0; i < 3; i++) {
// list.add("我是事件 " + integer + "拆分后的子事件" + i);
// // 通過flatMap中將可觀察者發送的事件序列先進行拆分,再將每個事件轉換為一個新的Observable,再發送給出去
// // 最終合并,再發送給被觀察者
// return Observable.fromIterable(list);
// }
//這里會生成新的可觀察者,然后與觀察者訂閱,像一種代理機制,通過事件攔截和處理實現事件序列的變換。
return Observable.just("事件 " + integer + " 轉換成的子事件 " + "test"+integer);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e("TAG", s);
}
});
log打印結果:
4.1.3、concatMap()
簡單使用
- 將被觀察者發送的事件序列進行 拆分 & 單獨轉換,再合并成一個新的事件序列,最后再進行發送
- 無序的將被觀察者發送的整個事件序列進行變換
- 用法和
flatMap()
相同,只是場景不同- 新合并生成的事件序列順序是有序的,即 嚴格按照舊序列發送事件的順序
// 采用RxJava基于事件流的鏈式操作
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
}
// 采用concatMap()變換操作符
}).concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
// final List<String> list = new ArrayList<>();
// for (int i = 0; i < 3; i++) {
// list.add("我是事件 " + integer + "拆分后的子事件" + i);
// // 通過concatMap中將可觀察者發送的事件序列先進行拆分,再將每個事件轉換為一個新的Observable,再發送給出去
// // 最終合并,再發送給被觀察者
// return Observable.fromIterable(list);
// }
//這里會生成新的可觀察者,然后與觀察者訂閱,像一種代理機制,通過事件攔截和處理實現事件序列的變換。
return Observable.just("事件 " + integer + " 轉換成的子事件 " + "test"+integer);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.e("TAG", s);
}
});
log打印結果:
4.1.4、Buffer()
簡單使用
- 場景:緩存被觀察者發送的事件
- 作用:定期從
可觀察者(Obervable)
需要發送的事件中 獲取一定數量的事件 & 放到緩存區中,最終發送
// 被觀察者 需要發送5個數字
Observable.just(1, 2, 3, 4, 5)
.buffer(3, 1) // 設置緩存區大小 & 步長
// 緩存區大小 = 每次從被觀察者中獲取的事件數量
// 步長 = 每次獲取新事件的數量
.subscribe(new Observer<List<Integer>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Integer> stringList) {
//
Log.e("TAG", " 緩存區里的事件數量 = " + stringList.size());
for (Integer value : stringList) {
Log.e("TAG", " 接收onNext事件 = " + value);
}
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收onError事件" );
}
@Override
public void onComplete() {
Log.e("TAG", "接收Complete事件");
}
});
log打印結果:
4.2、concat() / concatArray()
組合多個可觀察者
① 組合多個被觀察者一起發送數據,合并后 按發送順序串行執行
②concat() / concatArray()
二者區別:組合被觀察者的數量,即concat()組合被觀察者數量≤4個,而concatArray()則可>4個
4.2.1、concat()
concat():組合多個被觀察者(≤4個)一起發送數據
// 串行執行
Observable
.concat(
Observable.just(1, 2, 3),
Observable.just(4, 5, 6),
Observable.just(7, 8, 9),
Observable.just(10, 11, 12)
)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到onNext事件==" + value);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收到onError事件"+e.toString());
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
log打印結果:
4.2.2、concatArray()
concat():組合多個被觀察者(≤4個)一起發送數據
concatArray():組合多個被觀察者一起發送數據(可>4個)
// 串行執行
Observable.concatArray(Observable.just(1, 2, 3),
Observable.just(4, 5, 6),
Observable.just(7, 8, 9),
Observable.just(10, 11, 12),
Observable.just(13, 14, 15))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到了事件" + value);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "對Error事件作出響應");
}
@Override
public void onComplete() {
Log.e("TAG", "對Complete事件作出響應");
}
});
log打印結果:
4.3、merge() / mergeArray()
簡單使用
① 組合多個可觀察者一起發送數據,合并后 按時間線并行執行
② 二者區別:組合可觀察者的數量,即merge()
組合可觀察者數量≤4個,而mergeArray()
則可>4個
③ 區別上述concat()
操作符:同樣是組合多個可觀察者一起發送數據,但concat()
操作符合并后是按發送順序串行執行
4.3.1、merge()
簡單使用
merge()
:組合多個可觀察者(≤ 4個)一起發送數據
//合并后按照時間線并行執行
Observable.merge(
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS), // 從0開始發送、共發送3個數據、第1次事件延遲發送時間 = 1s、間隔時間 = 1s
Observable.intervalRange(2, 3, 1, 1, TimeUnit.SECONDS)) // 從2開始發送、共發送3個數據、第1次事件延遲發送時間 = 1s、間隔時間 = 1s
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long value) {
Log.e("TAG", "接收到onNext事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收到onError事件");
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
log打印結果:輸出結果 = 事件0,事件2 -> 事件1,事件3 -> 事件2,事件4
4.3.2、mergeArray()
簡單使用
mergeArray()
:組合多個可觀察者(≤ 4個)一起發送數據
Observable.mergeArray(
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS), // 從0開始發送、共發送3個數據、第1次事件延遲發送時間 = 1s、間隔時間 = 1s
Observable.intervalRange(2, 3, 1, 1, TimeUnit.SECONDS)) // 從2開始發送、共發送3個數據、第1次事件延遲發送時間 = 1s、間隔時間 = 1s
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long value) {
Log.e("TAG", "mergeArray--接收到onNext事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "mergeArray--接收到onError事件");
}
@Override
public void onComplete() {
Log.e("TAG", "mergeArray--接收到onComplete事件");
}
});
log打印結果:輸出結果 = 事件0,事件2 -> 事件1,事件3 -> 事件2,事件4
4.4、concatDelayError() / mergeDelayError()
簡單使用
- 使用concat()和merge()操作符時,其中1個可觀察者發出onError事件,則會馬上終止其他可觀察者繼續發送事件,如果希望onError事件推遲到其他可觀察者發送事件結束才再觸發發送onError事件,可使用concatDelayError()或者mergeDelayError操作符來解決
Observable.concat( //沒有使用concatDelayError()的情況
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onError(new NullPointerException()); // 發送Error事件,因為無使用concatDelayError,所以第2個Observable將不會發送事件
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}),
Observable.just(4, 5, 6))//沒有使用了concatDelayError(),事件4、5、6在onError事件后不再發射
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", " 接收到事件 "+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收到onError事件");
}
@Override
public void onComplete() {
Log.e("TAG", "接收到onComplete事件");
}
});
Observable.concatArrayDelayError(//使用了concatDelayError()的情況
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onError(new NullPointerException()); // 發送Error事件,因為使用了concatDelayError,所以第2個Observable將會發送事件,等發送完畢后,再發送錯誤事件
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}),
Observable.just(4, 5, 6))//使用了concatDelayError(),事件4、5、6在onError事件后可以發射
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "接收到了onError事件");
}
@Override
public void onComplete() {
Log.e("TAG", "接收到了onComplete事件");
}
});
log打印結果:下圖可知,不適用concatDelayonError
時,事件4、5、6沒有被發射出來,而使用concatDelayonError
時,會發射玩所有事件后,在發射onError事件,就是onError事件被延遲發射了,此情況mergeDelayError
雷同,代碼就省略了
4.5 合并多個事件Zip()
的簡單使用
① 該類型的操作符主要是對多個被觀察者中的事件進行合并處理
② 合并 多個被觀察者(Observable)發送的事件,生成一個新的事件序列(即組合過后的事件序列),并最終發送
③ 事件組合方式 = 嚴格按照原先事件序列 進行對位合并
④ 最終合并的事件數量 = 多個被觀察者(Observable)中數量最少的數量
//創建第1個被觀察者
Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.e("TAG", "可觀察者1發送了事件 1");
emitter.onNext(1);
// 為了方便展示效果,所以在發送事件后加入2s的延遲
Thread.sleep(2000);
Log.e("TAG", "可觀察者1發送了事件2");
emitter.onNext(2);
Thread.sleep(2000);
Log.e("TAG", "可觀察者1發送了事件3");
emitter.onNext(3);
Thread.sleep(2000);
Log.e("TAG", "可觀察者1發送了事件4");
emitter.onNext(4);
Thread.sleep(2000);
emitter.onComplete();
}
}).subscribeOn(Schedulers.io()); // 設置可觀察者1 在線程1中執行
//創建第2個可觀察者
Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.e("TAG", "可觀察者 2 發送了事件 A ");
emitter.onNext("A");
Thread.sleep(2000);
Log.e("TAG", "可觀察者 2 發送了事件 B ");
emitter.onNext("B");
Thread.sleep(2000);
Log.e("TAG", "可觀察者 2 發送了事件 C ");
emitter.onNext("C");
Thread.sleep(2000);
Log.e("TAG", "可觀察者 2 發送了事件 D ");
emitter.onNext("D");
Thread.sleep(2000);
emitter.onComplete();
}
}).subscribeOn(Schedulers.newThread());// 設置可觀察者 2 在 線程2中執行
// 假設不作線程控制,則該兩個被觀察者會在同一個線程中工作,即發送事件存在先后順序,而不是同時發送
// 使用zip變換操作符進行事件合并
// 注:創建BiFunction對象傳入的3個參數 ==可觀察者1的數據類型 可觀察者2的數據類型 合并后數據的數據類型
Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String string) throws Exception {
return integer + string;
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "onSubscribe");
}
@Override
public void onNext(String value) {
Log.e("TAG", "最終接收到的事件 = " + value);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "onError");
}
@Override
public void onComplete() {
Log.e("TAG", "onComplete");
}
});
log打印結果:
4.6 combineLatest()
的簡單使用
① 當兩個Observables中的任何一個發送了數據后,將先發送了數據的Observables 的最新(最后)一個數據 與 另外一個Observable發送的每個數據結合,最終基于該函數的結果發送數據
② 與Zip()的區別:Zip() = 按個數合并,即1對1合并;CombineLatest() = 按時間合并,即在同一個時間點上合并
Observable.combineLatest(
Observable.just(1L, 2L, 3L), // 第1個發送數據事件的Observable
Observable.intervalRange(0, 3, 2, 2, TimeUnit.SECONDS), // 第2個發送數據事件的Observable:從0開始發送、共發送3個數據、第1次事件延遲發送時間 = 2s、間隔時間 = 2s
new BiFunction<Long, Long, Long>() {
@Override
public Long apply(Long o1, Long o2) throws Exception {
// o1 = 第1個Observable發送的最新(最后)1個數據
// o2 = 第2個Observable發送的每1個數據
Log.e("TAG", "合并的數據是: "+ "第一個 "+o1 + " "+ "第二個 "+o2);
return o1 + o2;
// 合并的邏輯 = 相加
// 即第1個Observable發送的最后1個數據 與 第2個Observable發送的每1個數據進行相加
}
}).subscribe(new Consumer<Long>() {
@Override
public void accept(Long s) throws Exception {
Log.e("TAG", "合并的結果是: "+s);
}
});
log打印結果:
4.6 collect()
的簡單使用
① 將被觀察者Observable發送的數據事件收集到一個數據結構里
Observable.just(1, 2, 3 ,4, 5, 6)
.collect(
// 1. 創建數據結構(容器),用于收集被觀察者發送的數據
new Callable<ArrayList<Integer>>() {
@Override
public ArrayList<Integer> call() throws Exception {
return new ArrayList<>();
}
// 2. 對發送的數據進行收集
}, new BiConsumer<ArrayList<Integer>, Integer>() {
@Override
public void accept(ArrayList<Integer> list, Integer integer)
throws Exception {
// 參數說明:list = 容器,integer = 后者數據
list.add(integer);
// 對發送的數據進行收集
}
}).subscribe(new Consumer<ArrayList<Integer>>() {
@Override
public void accept(@NonNull ArrayList<Integer> s) throws Exception {
Log.e("TAG", "本次發送的數據是: "+s);
}
});
log打印結果:
4.7、startWith() / startWithArray()
發送事件前追加發送事件
① 在一個被觀察者發送事件前,追加發送一些數據 / 一個新的被觀察者
//在一個被觀察者發送事件前,追加發送一些數據
// 注:追加數據順序 = 后調用先追加
Observable.just(4, 5, 6)
.startWithArray(1, 2, 3) // 追加多個數據 = startWithArray()
.startWith(0) // 追加單個數據 = startWith()
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到了事件" + value);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "對Error事件作出響應");
}
@Override
public void onComplete() {
Log.e("TAG", "對Complete事件作出響應");
}
});
// 在一個被觀察者發送事件前,追加發送被觀察者 & 發送數據
// 注:追加數據順序 = 后調用先追加
Observable.just(4, 5, 6)
.startWith(Observable.just(1, 2, 3))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.e("TAG", "接收到了事件" + value);
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "對Error事件作出響應");
}
@Override
public void onComplete() {
Log.e("TAG", "對Complete事件作出響應");
}
});
log打印結果:
4.8、count()
統計發送事件數量
① 統計被觀察者發送事件的數量
// 注:返回結果 = Long類型
Observable.just(1, 2, 3, 4)
.count()
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.e("TAG", "發送的事件數量 = "+aLong);
}
});
log打印結果:
4.10、組合 / 合并操作符 總結
5、RxJava的線程控制(切換 / 調度 ):異步操作
① 指定 可觀察者 (
Observable
) / 觀察者(Observer
) 的工作線程類型
② 線程控制(也稱為調度 / 切換)功能性操作符中的:subscribeOn() 與 observeOn()
③Observable.subscribeOn(Schedulers.Thread)
:指定被觀察者 發送事件的線程(傳入RxJava內置的線程類型)
④Observable.observeOn(Schedulers.Thread)
:指定觀察者 接收 & 響應事件的線程(傳入RxJava內置的線程類型)
⑤subscribeOn(Schedulers.newThread())
:指定被觀察者 生產事件的線程
⑥observeOn(AndroidSchedulers.mainThread())
:指定觀察者 接收 & 響應事件的線程
5.1 指定可觀察者 發射線程 subscribeOn()
若Observable.subscribeOn()多次指定可觀察者 生產事件的線程,則只有第一次指定有效,其余的指定線程無效
observable.subscribeOn(Schedulers.newThread()) // 第一次指定被觀察者線程 = 新線程
.subscribeOn(AndroidSchedulers.mainThread()) // 第二次指定被觀察者線程 = 主線程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
//被觀察者的線程 = 第一次指定的線程 = 新的工作線程,第二次指定的線程(主線程)無效
5.2 指定觀察者 接收線程 subscribeOn()
若Observable.observeOn()多次指定觀察者 接收 & 響應事件的線程,則每次指定均有效,即每調用一次observeOn(),觀察者的線程就會切換一次
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread()) // 第一次指定觀察者線程 = 主線程
.doOnNext(new Consumer<String>() { // 生產事件
@Override
public void accept(String string) throws Exception {
Log.d("TAG", "第一次觀察者Observer的工作線程是: " + Thread.currentThread().getName());
}
})
.observeOn(Schedulers.newThread()) // 第二次指定觀察者線程 = 新的工作線程
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
}
}); // 生產事件
// 注:
// 1. 整體方法調用順序:觀察者.onSubscribe()> 被觀察者.subscribe()> 觀察者.doOnNext()>觀察者.onNext()>觀察者.onComplete()
// 2. 觀察者.onSubscribe()固定在主線程進行
log打印結果:
5.3、背壓策略詳情請看--關于 RxJava 最友好的文章系列
被觀察者發送事件速度遠快于觀察者的處理速度的情況下,一種告訴上游的被觀察者降低發送速度的策略
// 步驟1:創建被觀察者 = Flowable
Flowable.create(new FlowableOnSubscribe<Integer>() {
@Override
public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
Log.e("TAG", "發送事件 1");
emitter.onNext(1);
Log.e("TAG", "發送事件 2");
emitter.onNext(2);
Log.e("TAG", "發送事件 3");
emitter.onNext(3);
Log.e("TAG", "發送完成");
emitter.onComplete();
}
}, BackpressureStrategy.ERROR)
.subscribe(new Subscriber<Integer>() {
// 步驟2:創建觀察者 = Subscriber & 建立訂閱關系
@Override
public void onSubscribe(Subscription s) {
Log.e("TAG", "onSubscribe");
s.request(3);
}
@Override
public void onNext(Integer integer) {
Log.e("TAG", "接收到了事件" + integer);
}
@Override
public void onError(Throwable t) {
Log.e("TAG", "onError: ", t);
}
@Override
public void onComplete() {
Log.e("TAG", "onComplete");
}
});
6、錯誤處理 使用代碼示例與詳細講解
發送事件過程中,遇到錯誤時的處理機制,
網絡請求失敗,加載本地,重試等
操作符有
1、
onErrorReturn()
: 遇到錯誤時,發送1個特殊事件 & 正常終止
①、可捕獲在它之前發生的異常
2、
onErrorResumeNext()
: 遇到錯誤時,發送1個新的Observable
①、onErrorResumeNext()
攔截的錯誤 =Throwable
;若需攔截Exception
請用onExceptionResumeNext()
②、若onErrorResumeNext()
攔截的錯誤 =Exception
,則會將錯誤傳遞給觀察者的onError
方法
3、
onExceptionResumeNext()
:遇到錯誤時,發送1個新的Observable
①、onExceptionResumeNext()
攔截的錯誤 =Exception
;若需攔截Throwable
請用onErrorResumeNext()
②、若onExceptionResumeNext()
攔截的錯誤 =Throwable
,則會將錯誤傳遞給觀察者的onError
方法
4、
retry()
: 重試,即當出現錯誤時,讓被觀察者(Observable
)重新發射數據
①、接收到onError()
時,重新訂閱 & 發送事件
②、Throwable
和Exception
都可攔截
5、
retryUntil()
: 出現錯誤后,判斷是否需要重新發送數據
①、若需要重新發送 & 持續遇到錯誤,則持續重試
②、作用類似于retry(Predicate predicate)
③、具體場景:類似于retry(Predicate predicate)
,唯一區別:返回true
則不重新發送數據事件。
6、
retryWhen()
: 重試,即當出現錯誤時,讓被觀察者(Observable
)重新發射數據
①、接收到onError()
時,重新訂閱 & 發送事件
②、Throwable
和Exception
都可攔截
7、
retryWhen()
: 遇到錯誤時,將發生的錯誤傳遞給一個新的被觀察者(Observable
),并決定是否需要重新訂閱原始被觀察者(Observable
)& 發送事件
7、重復發送 使用代碼示例與詳細講解
重復不斷地發送被觀察者事件
對應操作符類型:repeat()
&repeatWhen()
1、
repeat()
: 無條件地、重復發送 被觀察者事件
①、具備重載方法,可設置重復創建次數
2、
repeatWhen()
: 有條件地、重復發送 被觀察者事件①、將原始
Observable
停止發送事件的標識(Complete() / Error()
)轉換成1個Object
類型數據傳遞給1個新被觀察者(Observable
),以此決定是否重新訂閱 & 發送原來的Observable
②、若新被觀察者(Observable
)返回1個Complete / Error
事件,則不重新訂閱 & 發送原來的Observable
③、若新被觀察者(Observable
)返回其余事件時,則重新訂閱 & 發送原來的Observable
8、compose
與Transformer
消除重復代碼
8.1、在使用RXJava與Retrofit請求網絡時,遇到過這樣的場景,在IO線程請求網絡解析數據,接著返回主線程setData、更新View試圖,代碼如下:
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
8.2、這樣肯定是沒問題的,但是如果請求網絡的次數多了,豈不是每個地方都要寫一遍?,并且同時又不想去破環RX的鏈式結構,怎么辦呢,有一個不是唯一的辦法,就是使用操作符
RetrofitClient.getData("網絡接口URL")
.requestNetData("參數1","參數2")
.compose(CommonTransformer())//自定義ObservableTransformer,完成線程切換
.subscribe(subscriber);
就是用 .compose(schedulersTransformer())
這一行一行代碼就完成了線程切換,代替了.subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())
這段代碼
8.3、實現
ObservableTransformer
,完成線程切換,然后使用compose()
操作符
/**
* ================================================
* Created by ${chenyuexueer}
* 說明:實現ObservableTransformer,完成線程切換,使用compose()操作符
* ================================================
*/
Observable.Transformer schedulersTransformer() {
return new Observable.Transformer() {
@Override
public Object call(Object observable) {
return ((Observable) observable).subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
//一行代碼搞定,使用情況如下:
//observable.compose (schedulersTransformer()).subscribe(subscriber)
- 筆記所參考文章
Android RxJava:組合 / 合并操作符 詳細教程
Android:這是一篇 清晰 & 易懂的Rxjava 入門教程
Android RxJava:最基礎的操作符詳解 - 創建操作符
Android RxJava:圖文詳解 變換操作符
Android RxJava:組合 / 合并操作符 詳細教程
Android RxJava:功能性操作符 全面講解
給 Android 開發者的 RxJava 詳解---作者:拋物線
Android RxJava:細說 線程控制(切換 / 調度 )(含Retrofit實例講解)
一個外國大神的Rxjava的demo
關于 RxJava 最友好的文章—— RxJava 2.0 全新來襲
關于RxJava最友好的文章