1.前言
由于Rxjava是一个变种的观察者设计模式,前面也已经说过了,Rxjava的设计是 一个开始节点,一个结束节点。
但是由于Rxjava提供了很多方便的操作符,使得我们的被观察着把数据发送到观察者的途中,我们可以对被观察着进行变形修改。
Rxjava是一个流式的API集合,所以我们可以通过一条线的方式梳理我们的逻辑,有可能会有多次变换操作,最终拿到想要的结果
画个草图
接下来讲讲常见的变换操作符有哪些。
- Map
- flatMap
- concatMap
- groupBy
- buffer
2.变换型操作符
2.1 Map操作符(使用场景-多)
说明
Observable.map() map操作符是一个简单类型的变换操作,把一个类型通过加工成另外一种类型或者是自己想要的值的结果类型 比如 从int通过自己的逻辑操作变身为String类型等
举例
Observable.just("张三")
.map(new Function<String, Boolean>() {
@Override
public Boolean apply(String name) throws Exception {
return name.equals("张三");
}
}).subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Boolean b) {
Log.i(TAG, "onNext: " + b);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
在这里 我们在上游发送的是一个String类型的数据,接收的地方是Boolean类型,在中间 我们就通过map操作符,把String对象转换成了我们想要的值发送出去了。 所以我们在下游观察者里面只需要关心最终的结果就行了。不需要关心中途的判断逻辑。这样一套流式的代码写下来也方便阅读
输出结果
I/MainActivity: onNext: true
2.2 flatMap操作符(使用场景-多)
说明
Observable.flatMap()将一个简单数据类型 变换为一个被观察者类型,
例子
Observable.just("张三")
.flatMap(new Function<String, Observable<String>>() {
@Override
public Observable<String> apply(String name) throws Exception {
return Observable.just("name = " + name);
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String str) {
Log.i(TAG, "onNext: " + str);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
输出结果:
I/MainActivity: onNext: name = 张三
2.3 concatMap操作符(使用场景-多)
说明
和flatMap一样的使用,唯一的区别就是发送出来的数据是有序的,就说明如果上游发出的数据是一个集合类型的时候,
如果你又要想保持顺序的输出,那么你就需要选择使用concatMap来实现。(如果市异步操作,可以采用该操作符来实现)
例子
Observable.just("www.baidu.com", "www.sina.com", "www.163.com")
.concatMap(new Function<String, Observable<String>>() {
@Override
public Observable<String> apply(String hostName) throws Exception {
return getIPAddress(hostName);
}
})
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String str) {
Log.i(TAG, " " + str + " , currentThread = " + Thread.currentThread());
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
private Observable<String> getIPAddress(final String hostName) {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
InetAddress ip = null;
try {
ip = InetAddress.getByName(hostName);
String hostAddress = ip.getHostAddress();
emitter.onNext(hostName + " => " + hostAddress);
// 如果是concatMap需要调用该方法,否则会阻塞
emitter.onComplete();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}).subscribeOn(Schedulers.io());
}
输出结果 (有序的)
I/MainActivity: www.baidu.com => 180.101.49.11 , currentThread = Thread[RxCachedThreadScheduler-1,5,main]
I/MainActivity: www.sina.com => 183.136.135.213 , currentThread = Thread[RxCachedThreadScheduler-2,5,main]
I/MainActivity: www.163.com => 183.131.64.220 , currentThread = Thread[RxCachedThreadScheduler-1,5,main]
I/MainActivity: onComplete:
对比flatMap的输出结果 这里就贴上面的代码 只不过是把concatMap改为flatMap
I/MainActivity: www.163.com => 183.131.64.254 , currentThread = Thread[RxCachedThreadScheduler-3,5,main]
I/MainActivity: www.sina.com => 115.238.192.239 , currentThread = Thread[RxCachedThreadScheduler-2,5,main]
I/MainActivity: www.baidu.com => 180.101.49.11 , currentThread = Thread[RxCachedThreadScheduler-1,5,main]
上面可以看到concatMap和flatMap的输出结果是不一致的,concatMap的输出结果是一致的,flatMap是无序的。
2.4 groupBy操作符(使用场景-多)
说明
groupBy 根据一定的条件将数据分组,类似于用map保存分组后的数据
例子
Observable.just(1,2,3,4,5,6)
.groupBy(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return integer>3?"小学":"幼儿园";
}
}).subscribe(new Consumer<GroupedObservable<String, Integer>>() {
@Override
public void accept(GroupedObservable<String, Integer> stringIntegerGroupedObservable) throws Exception {
System.out.println("stringIntegerGroupedObservable = [" + stringIntegerGroupedObservable.getKey() + "]");
stringIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("stringIntegerGroupedObservable.getKey() [" + integer + "]");
}
});
}
});
输出结果,按照幼儿园和小学分组分开打印,这里需要注意的是
I/System.out: stringIntegerGroupedObservable = [幼儿园]
I/System.out: stringIntegerGroupedObservable.getKey() [1]
I/System.out: stringIntegerGroupedObservable.getKey() [2]
I/System.out: stringIntegerGroupedObservable.getKey() [3]
I/System.out: stringIntegerGroupedObservable = [小学]
I/System.out: stringIntegerGroupedObservable.getKey() [4]
I/System.out: stringIntegerGroupedObservable.getKey() [5]
I/System.out: stringIntegerGroupedObservable.getKey() [6]
2.5 buffer操作符(使用场景-一般)
说明
buffer(nunmber) 根据number数值分组发射number组的数据, 意味着下游接收的数据是一个list
例子
Observable.just(1, 2, 3, 4, 5, 6)
.buffer(2).subscribe(new Observer<List<Integer>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Integer> integers) {
Log.i(TAG, "onNext: "+integers);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
输出结果,因为这里number是2 所以一组同时发射2条数据,如果最后剩余的数据不满足number,则一次发射完
I/MainActivity: onNext: [1, 2]
I/MainActivity: onNext: [3, 4]
I/MainActivity: onNext: [5, 6]