了解 Rxjava, 从其操作符开始
RxJava 的操作符可以划分为下面几类,分别是:
1:创建操作符
create 操作符
create 操作符用于创建被观察者 Observable ,代码如下:
//创建被观察者
Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(1+" ");
emitter.onComplete();
}
});
//观察者
Observer observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onNext(String s) {
System.out.println(s+" ");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
};
//产生订阅关系
observable.subscribe(observer);
如上代码所示,我们使用create 操作符创建了被观察者,并创建了观察者,调用 Observable.subscribe(Observer); 便可产生订阅关系,当产生订阅关系之后,便可以进行事件的传递,这里在 Observer (被观察者) 中发送事件,可传递到 Observer(观察者) 中去,同时我们也发现在 Observer 中含有其他方法,如 onSubscribe() (产生订阅关系的时候会调用), onNext() (在被观察者发送事件的时候会调用), onError() (当出现异常登情况时会调用该方法) , onComplete() (当被观察者调用 emitter.onComplete(); 时会调用 代表事件发送完毕,后面被观察者再发送事件,观察者也接受不到)
下面,我们再来看下上述代码的执行结果:
onSubscribe //产生订阅
1 //发送事件
onComplete //事件发送完毕
除了 create 操作符外,还有其他创建操作符:
just 创建操作符
just 操作符可以说是简化的 create 操作符,eg:
Observable observable = Observable.just("12345");
Observer observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable.subscribe(observer);
如上,直接创建了 Observable 和 Observer ,这样写法会较之前而言简化一些。但得到的结果是一样的。
然后,其实我们还可以再接着简化:
Observable.just("12345").subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
再接着简化:
Observable.just("12345").subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
如上三种写法,得到的结果均是相同的。
fromArray 创建操作符
fromArray 操作符适用于发射的数据是一个数组的情况,类似一个遍历数组的功能,eg:
Observable.fromArray(new Integer[]{1,2,3,4,5}) //创建 observable
.subscribe(new Observer<Integer>() {//创建 observer 并产生订阅
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
System.out.println(integer);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
得到的结果如下:
1
2
3
4
5
从如上 log 中可以看到,在事件上游往下游传递过程中,遍历了数组的每一个元素,并单独发送事件。
empty 创建操作符
empty 创建操作符用于创建一个空事件的被观察者,eg:
Observable.empty().subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe()");
}
@Override
public void onNext(Object o) {
System.out.println("onNext()");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete()");
}
});
打印 log 如下:
onSubscribe() //创建订阅
onComplete() //完成事件发送
注:由于 empty 操作符为创建一个空事件的操作符,所以不会调用 onNext() 方法。
如上为平常用得稍微频繁些的操作符,还有一些其他操作符,如 defer , timer , interval 等也属于创建操作符,与上述操不多,这里不再赘述,有用到时可以查看官方文档中的操作符列表。
2:转换操作符
转换操作符,是在从 Observable 发射事件到 Observer 的途中,将发送的事件进行一系列操作的操作符。下面来具体看下一部分常用的转换操作符:
map 转换操作符,下面看图说话,直接上代码,eg:
//创建被观察者
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(2);
emitter.onNext(4);
emitter.onNext(7);
emitter.onComplete();
}
}).map(new Function<Integer, String>() { //使用 map 操作符进行变换,将传递的integer转换成了String
@Override
public String apply(Integer integer) throws Exception {
return "apply:" + integer;
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
//打印 log
System.out.println(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
得到的 log 如下:
apply:2
apply:4
apply:7
从结果中不难得出,我们在 Observer 中的到的事件 已经是经过了 map 处理后的 事件数据了。
此类转换可以用于加载图片等操作,伪代码可如下进行操作:
Observable.just("header.png")//发射图片 url
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
return loadImage(s);//通过 s 这个图片 url 加载图片
}
})
.subscribeOn(Schedulers.io()) //耗时操作在子线程中执行
.observeOn(AndroidSchedulers.mainThread()). //调度到主线程显示
subscribe(new Consumer<Bitmap>() {
@Override
public void accept(Bitmap bitmap) throws Exception {
showBitmap();
}
});
flatmap 变换操作符:
flatMap 是一个很有趣的东西,我坚信你在实际开发中会经常用到。它可以把一个发射器 Observable 通过某种方法转换为多个 Observables,然后再把这些分散的 Observables装进一个单一的发射器 Observable。但有个需要注意的是,flatMap 并不能保证事件的顺序,如果需要保证,需要用到我们下面要讲的 ConcatMap。eg:
public void testFlatmap(){
Observable.just("getConfig","login")
.flatMap(new Function<String, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(String s) throws Exception {
return createResponse(s);
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println("onNext--->"+s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
public Observable<String> createResponse(final String s){
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("login----->"+s);
}
});
}
得到的 log 如下:
onNext--->login----->getConfig
onNext--->login----->login
groupBy 分组操作符:
groupBy 操作符 是将事件通过一定的逻辑分成组别,eg:
Observable.just(2,5,1,7,4,9)
.groupBy(new Function<Integer, Boolean>() {
@Override
public Boolean apply(Integer integer) throws Exception {
return integer > 5? true : false;
}
}).subscribe(new Consumer<GroupedObservable<Boolean, Integer>>() {
@Override
public void accept(GroupedObservable<Boolean, Integer> booleanIntegerGroupedObservable) throws Exception {
//打印组别
System.out.println(booleanIntegerGroupedObservable.getKey());
}
});
得到的 log 如下:
false
true
上面我们是打印了归类后的组别,下面再来打印下具体的每个组别中的数据:
Observable.just(2,5,1,7,4,9)
.groupBy(new Function<Integer, Boolean>() {
@Override
public Boolean apply(Integer integer) throws Exception {
return integer > 5? true : false;
}
}).subscribe(new Consumer<GroupedObservable<Boolean, Integer>>() {
@Override
public void accept(final GroupedObservable<Boolean, Integer> booleanIntegerGroupedObservable) throws Exception {
//打印组别
//System.out.println(booleanIntegerGroupedObservable.getKey());
//遍历打印 具体组别的数据
booleanIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
//获取到组的key
boolean key = booleanIntegerGroupedObservable.getKey();
//组装打印
System.out.println("key:"+ key + "vaule:" + integer);
}
});
}
});
得到的 log 如下:
key:false vaule:2
key:false vaule:5
key:false vaule:1
key:true vaule:7
key:false vaule:4
key:true vaule:9
可以看到,在我们的判断条件下(value > 5-->true)
buffer 分组操作符
buffer 是将一组数据分为多组数据,函数有多个重载,可以了解一下,skip 代表步长,count 代表每一组的数据个数,eg:
Observable.fromArray(new Integer[]{1,2,3,4,5,6,7,8,9})
.buffer(3)
// .buffer(3,2)
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println(integers);
}
});
得到的 log 如下:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
从上述 log 可以清晰看到,被分为了多组且每组至多为 count 个数据。
使用场景:
10000条数据插入到数据库中时 每一条数据产生都需要时间
如果产生一条 插入一条比较浪给时间,全部一次性插入用户等的太久
采取buffer的形式 将10000条 分成 一小段执行
reduce 操作符
reduce 是将数据进行处理后合并成一个总的数据,发射给观察者,eg:
Observable.just(2,3,4,5,6,7)
.reduce(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
return integer + integer2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
得到的 log 如下:
27//只有最终结果
再来看下 scan 操作符,eg:
Observable.just(1,2,3,4,5,6)
.scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
return integer + integer2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
得到的结果如下:
1
3
6
10
15
21
scan 与 reduce 的 功能都是相同的,不同指出在于:scan 同时关注过程和结果,而 reduce 只关注结果。
window 操作符:
window 按照实际划分窗口,将数据发送给不同的 Observable
Observable.interval(1,TimeUnit.SECONDS)
.take(15)
.window(3,TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Observable<Long>>() {
@Override
public void accept(Observable<Long> longObservable) throws Exception {
longObservable.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onNext(Long aLong) {
System.out.println(aLong);
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
}
});
得到的 log 如下:
19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 0
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 1
* 19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
* 19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 2
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 3
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 4
* 19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
* 19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 19232-19232/com.example.justh.rxjavatrain I/System.out: 5
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 6
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 7
* 19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
* 19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 119232-19232/com.example.justh.rxjavatrain I/System.out: 8
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 9
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 10
* 19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
* 19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 11
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 12
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 13
* 19232-19749/com.example.justh.rxjavatrain I/System.out: onComplete
* 19232-19232/com.example.justh.rxjavatrain I/System.out: onSubscribe
* 19232-19750/com.example.justh.rxjavatrain I/System.out: 14
* 19232-19750/com.example.justh.rxjavatrain I/System.out: onComplet
到这里,常用的变换操作符就差不许多了,其余的可以参考官方文档上的相关叙述。