flatMap 一般用于输出一个 Observable,而其随后的 subscribe 中的参数也跟 Observable 中的参数一样。
下面再提供一个使用场景,这个场景属于嵌套的网络请求,比如我们想先进行一次网络请求得到图片的url,然后根据url再进行网络请求得到图片,最后设置给 ImageView ,这种情况下由url到 Bitmap 的转换用 map 是无法实现的,可以使用 flatmap。
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> observableEmitter) throws Exception {
String url = getImageUrl(mUrl);
observableEmitter.onNext(url);
observableEmitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.flatMap(new Function<String, ObservableSource<Bitmap>>() {
@Override
public ObservableSource<Bitmap> apply(@NonNull final String url) throws Exception {
return Observable.create(new ObservableOnSubscribe<Bitmap>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Bitmap> observableEmitter) throws Exception {
Bitmap bitmap = getBitmap(url);
observableEmitter.onNext(bitmap);
observableEmitter.onComplete();
}
});
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Bitmap>() {
@Override
public void accept(Bitmap bitmap) throws Exception {
mImageView.setImageBitmap(bitmap);
}
});
更多flatmap 案例
private void initData() {
Flowable.fromIterable(getAllStudentInfoById())
.flatMap(new Function<Student, Publisher<Source>>() {
@Override
public Publisher<Source> apply(@NonNull Student student) throws Exception {
return Flowable.fromIterable(student.mSources);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Source>() {
@Override
public void accept(@NonNull Source source) throws Exception {
String content = "sourceName:" + source.name + " source score:" + source.score;
// mTextView.setText(content);
Log.i(TAG, content);
}
});
}
public List<Student> getAllStudentInfoById() {
List<Student> studentList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
List<Source> sources = new ArrayList<>();
for (int j = 0; j < 3; j++) {
Random random = new Random();
int score = random.nextInt(100);
Source source = new Source(j, "科目-" + j, score);
sources.add(source);
}
Student student = new Student("xxx-" + i, i, sources);
studentList.add(student);
}
return studentList;
}
concatMap操作符的功能和flatMap是非常相似的,只是有一点,concatMap 最终输出的数据序列和原数据序列是一致,它是按顺序链接Observables,而不是合并(flatMap用的是合并)。
// concatmap
Observable.fromArray(1,2,3,4,5)
.concatMap(new Function<Integer, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(@NonNull Integer integer) throws Exception {
int delay = 0;
if(integer == 3){
delay = 500;//延迟500ms发射
}
return Observable.just(integer *10).delay(delay, TimeUnit.MILLISECONDS);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
Log.e(TAG,"accept:"+integer);
}
});
打印结果为// flatmap
Observable.fromArray(1,2,3,4,5)
.flatMap(new Function<Integer, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(@NonNull Integer integer) throws Exception {
int delay = 0;
if(integer == 3){
delay = 500;//延迟500ms发射
}
return Observable.just(integer *10).delay(delay, TimeUnit.MILLISECONDS);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
Log.e(TAG,"accept:"+integer);
}
});
打印结果