目錄
RxJava提供了大量操作符,本文主要列一些常用到的操作符
1. 創建類型
create
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
}
});
just
Observable.just(1).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
fromArray
Observable.fromArray(1).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
fromCallable
Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return "1";
}
});
它們之間的區別
- create需要主動調用onNext來發送事件,這樣下游才能接收到事件
- just用于發送有限個事件(1到9個),fromArray用于發送數組類型的事件集
2. 轉換型
map
圖中map的作用就是將上游的圓形事件轉化成了矩形事件,下面來看看代碼例子
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
}
}).map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.valueOf(s);
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("TAG","integer:"+integer);
}
});
結果輸出
D/TAG: integer:1
結果分析
上游我們發送了一個String類型的數據
下游我們收到的是一個Integer類型的數據
map的作用就是將上游的數據轉化成下游所需要的任意類型
flatMap
flatMap與map的區別
map只能處理一對一的轉換,而flatMap可以處理一對多,多對多的轉換
map直接返回的是要轉化的類型,flatMap返回的是Observable對象,這將相當于創建了一個新的管道,下游收到的將是這個管道的東西。
舉個栗子
在舉例子之前,我們先看一段代碼,來看看Observable的的create,just,fromXXX的區別
String[] courses={"數據結構","操作系統","算法導論"};
String[] students={"王二","張三","李四"};
List<Course> courseList=new ArrayList<>();
for(int i=0;i<courses.length;i++){
Course course=new Course();
course.name=courses[I];
courseList.add(course);
}
List<Student> studentList=new ArrayList<>();
for(int i=0;i<students.length;i++){
Student student=new Student();
student.name=students[I];
student.courseList=courseList;
studentList.add(student);
}
Observable.create(new ObservableOnSubscribe<Student>() {
@Override
public void subscribe(ObservableEmitter<Student> emitter) throws Exception {
}
}).subscribe(new Consumer<Student>() {
@Override
public void accept(Student student) throws Exception {
Log.d("TAG","create");
}
});
Observable.just(studentList).subscribe(new Consumer<List<Student>>() {
@Override
public void accept(List<Student> students) throws Exception {
Log.d("TAG","just");
}
});
Observable.fromIterable(studentList).subscribe(new Consumer<Student>() {
@Override
public void accept(Student students) throws Exception {
Log.d("TAG","fromIterable");
}
});
輸出結果
D/TAG: just
D/TAG: fromIterable
D/TAG: fromIterable
D/TAG: fromIterable
結果分析
create沒有輸出,是因為沒有主動調用next事件
create只能傳遞單對象,如果是事件集,需要在subscribe寫for循環
jsut可以直接傳遞事件集,但接收方接收的也是事件集,可以在接收方主動寫for循環來拿到每一個對象
fromXXX中也很多個系列,如果是集合則調用fromIterable,數組則可以調用fromArray,from可以直接傳遞事件集,接收方也會自動將集合遍歷
回到主題,假設我們現在有這樣一個需求,上游發送一個學生集合,下游需要打印出每一個學生的各個課程,每個學生都有多門課程。
發送學生對象,接收課程對象,我們首先想到的是map的轉化
Observable.fromIterable(studentList).map(new Function<Student, List<Course>>() {
@Override
public List<Course> apply(Student student) throws Exception {
Log.d("TAG",student.name);
return student.courseList;
}
}).subscribe(new Consumer<List<Course>>() {
@Override
public void accept(List<Course> courses) throws Exception {
for(int i=0;i<courses.size();i++){
Log.d("TAG",courseList.get(i).name);
}
}
});
輸出結果
D/TAG: 王二
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
D/TAG: 張三
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
D/TAG: 李四
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
這樣寫是沒有問題的,但在輸出時,多了一層for循環的嵌套,我們來試試flatMap
Observable.fromIterable(studentList).flatMap(new Function<Student, ObservableSource<Course>>() {
@Override
public ObservableSource<Course> apply(Student student) throws Exception {
Log.d("TAG",student.name);
return Observable.fromIterable(student.courseList);
}
}).subscribe(new Consumer<Course>() {
@Override
public void accept(Course course) throws Exception {
Log.d("TAG",course.name);
}
});
輸出結果
D/TAG: 王二
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
D/TAG: 張三
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
D/TAG: 李四
D/TAG: 數據結構
D/TAG: 操作系統
D/TAG: 算法導論
結果分析
兩種方式都能達到我們的目的,即輸出每一個學生的多門課程。
不過顯然flatMap比map少了一層嵌套,代碼格式看著更舒服。
3. 其它
doOnNext
- do系列的作用是side effect,當onNext發生時,它被調用,不改變數據流。
- doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情。
舉個例子
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
...
}
});
在使用User信息之前,在doOnNext方法里對User信息進行了處理,最后執行了subscriber里的OnNext方法。
zip
簡單來講,zip可以將多個操作合并在一起
場景,有一個頁面在展示之前,需要等待兩個接口都請求完成之后,將兩個接口的數據整合在一起,然后才展示頁面
看一下zip的源碼
@SuppressWarnings("unchecked")
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T1, T2, R> Observable<R> zip(
ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2,
BiFunction<? super T1, ? super T2, ? extends R> zipper) {
ObjectHelper.requireNonNull(source1, "source1 is null");
ObjectHelper.requireNonNull(source2, "source2 is null");
return zipArray(Functions.toFunction(zipper), false, bufferSize(), source1, source2);
}
舉個例子,我們的兩個接口分別是
Observable<Response1>和Observable<Response2>
調用zip操作可以在Response1和Response2都請求完之后,合并成Response3,即BiFunction< Response1,Response2,Response3>
關于RxJava的使用就先到這,要了解更多,請點擊文章開頭的鏈接學習,接下來我來談一談RxJava和Retrofit的混合使用