rxjava2变换运算符
Map
将Observable发出的每个项目通过函数应用转换后发出。
上面的图很好的解释了map方法的含义。在工作中也很常遇见这种情况,源Observable发出的项,不是我们直接想要的,这时候就需要对Observable发出的项变换处理。举个例子:
private void doSomeWork() {
Observable.just("0", "1", "2", "3", "4", "5", "6", "7", "8", "9")
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return "this is map apply s is " + s;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String value) throws Exception {
Log.d(TAG, " accept : value : " + value);
}
});
}
打印结果
accept : value : this is map apply s is 0
accept : value : this is map apply s is 1
accept : value : this is map apply s is 2
accept : value : this is map apply s is 3
accept : value : this is map apply s is 4
accept : value : this is map apply s is 5
accept : value : this is map apply s is 6
accept : value : this is map apply s is 7
accept : value : this is map apply s is 8
accept : value : this is map apply s is 9
源发出去的是string类型的字符串0,1,2等等,通过map中函数里面的方法,我们变换处理了源Observable发出的项,转换后发出的类型可以是任何类型,我们这里处理后还是string,只是将数据内容改变了下。
FlatMap
将Observable发出的项目转换为Observables,然后将这些项目的排放量变为单个Observable。FlatMap运算符通过将您指定的函数应用于源Observable发出的每个项来转换Observable,其中该函数返回一个本身发出项的Observable。FlatMap合并这些结果Observable的发射,将这些合并的结果作为自己的序列发出。
请注意,FlatMap会合并这些Observable的发射,但它们可能交错。
上面我们已经了解了rxjava中Map的方法,FlatMap比Map多了一层意思,就是flat平铺。Map只是对源Observable发出的项简单的一对一用函数转换,FlatMap可以对源Observable发出的项用函数分解或者扩展成多个项,然后将所有的项平铺的发送出来。
举个例子,源Observable只发送int数据0,1,2,3,经过FlatMap里的函数扩展后,发射出来的数据变成了3倍。
private void doSomeWork() {
Observable.just(0, 1, 2, 3)
.flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("apply data is " + integer + ",i is " + i);
}
return Observable.fromIterable(list).delay((3 - integer) * 10, TimeUnit.MILLISECONDS);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String value) throws Exception {
Log.d(TAG, " accept : value : " + value);
}
});
}
打印结果
accept : value : apply data is 3,i is 0
accept : value : apply data is 3,i is 1
accept : value : apply data is 3,i is 2
accept : value : apply data is 2,i is 0
accept : value : apply data is 2,i is 1
accept : value : apply data is 2,i is 2
accept : value : apply data is 1,i is 0
accept : value : apply data is 1,i is 1
accept : value : apply data is 1,i is 2
accept : value : apply data is 0,i is 0
accept : value : apply data is 0,i is 1
accept : value : apply data is 0,i is 2
由于FlatMap合并数据的时候采用的是merge但方法,所以可以看见最终发射出来的项顺序和源发射出来的项顺序不一定对应。这就是上面说的它们可能交错。如果想最终变换后的项顺序和源发出的顺序一致,可以看看下面的concatMap。
concatMap
作用和FlatMap一样,只是与FlatMap不同的是,他最终输出的项顺序和源发出的项顺序是一致的。
将上面FlatMap的例子改成concatMap,我们可以看看打印的结果来比较下区别
private void doSomeWork() {
Observable.just(0, 1, 2, 3)
.concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("apply data is " + integer + ",i is " + i);
}
return Observable.fromIterable(list).delay((3 - integer) * 10, TimeUnit.MILLISECONDS);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String value) throws Exception {
Log.d(TAG, " accept : value : " + value);
}
});
}
打印结果
accept : value : apply data is 0,i is 0
accept : value : apply data is 0,i is 1
accept : value : apply data is 0,i is 2
accept : value : apply data is 1,i is 0
accept : value : apply data is 1,i is 1
accept : value : apply data is 1,i is 2
accept : value : apply data is 2,i is 0
accept : value : apply data is 2,i is 1
accept : value : apply data is 2,i is 2
accept : value : apply data is 3,i is 0
accept : value : apply data is 3,i is 1
accept : value : apply data is 3,i is 2
可以看见concatMap结果集的顺序和按照源发出的顺序一致
flatMapIterable
flatMapIterable和FlatMap的工作方式大致相同,不同的是对源项处理生成Iterables而不是生成Observable。
其实flatMapIterable就是一个可以自动迭代循环处理结果集的flatMap。
一样举个例子
private void doSomeWork() {
Observable.just(0, 1, 2, 3)
.flatMapIterable(new Function<Integer, Iterable<String>>() {
@Override
public Iterable<String> apply(Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("apply data is " + integer + ",i is " + i);
}
return list;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String value) throws Exception {
Log.d(TAG, " accept : value : " + value);
}
});
}
打印结果
accept : value : apply data is 0,i is 0
accept : value : apply data is 0,i is 1
accept : value : apply data is 0,i is 2
accept : value : apply data is 1,i is 0
accept : value : apply data is 1,i is 1
accept : value : apply data is 1,i is 2
accept : value : apply data is 2,i is 0
accept : value : apply data is 2,i is 1
accept : value : apply data is 2,i is 2
accept : value : apply data is 3,i is 0
accept : value : apply data is 3,i is 1
accept : value : apply data is 3,i is 2
对于map相关的就简单的写这些,其他的map方法也都是思路大同小异,最多也只是对结果特殊的处理了下,类似flatMapIterable和flatMap之间的差异,我就不一一举例说明了。
参考资料,参考但不局限以下链接
http://reactivex.io/documentation/operators/flatmap.html