重拾Android之路(十八)RxJava的函数
好久没有写博客了,今天趁着这个时间,把自己复习的RxJava再重新梳理一遍。这里基本的概念已经没有什么问题了,关键是RxJava中的方法非常之多,有时候也会有各种各样的改动,那么在这里将大部分的RxJava中的方法做一个汇总,希望在自己学习的同时,也能帮助后来者。
本篇文章是以RxJava2.2.3版本为核心
部分RxJava方法表格
编号 | 方法名 | 一般使用方法 | 功能 |
---|---|---|---|
1 | create | Observable.create(ObservableOnSubscribe) | 产生一个Observable被观察者对象 |
2 | map | Observable.create(xxx).map(Function<xxx,xxx>()) | 基本操作符,对每一个被触发的事件都要执行当前函数 |
3 | flatMap | Observable.create(xxx).flatMap(Function<Interget,ObservableSource) | 把一个Observable听过某种方法转换成多个Observables,然后再讲这些分散的Observables分装到单一的发射器Observable中不能保证发射顺序 |
4 | concatMap | Observable.create(xxx).concatMap(Function<Interger,ObservableSource>) | 跟flatMap相类似,不过是有序的 |
5 | zip | Observable.create(xxx).zio(发射器1,发射器2,BiFunction<String,Integer,String>) | 将两个发射器的数据进行整合,相当于是两两配对 |
6 | interval | Observable.interval(1,TimeUnit.SECONDS) | 每隔一段时间就产生一个数字,默认从0开始,一次递增1至无穷大 |
7 | repeat | Observable.create(xxx).repeat(3) | 重复执行 |
8 | just | Observable.just(1,2,3) | 默认创建一个Observable对象,并且依次发送1,2,3 |
9 | range | Observable.range(1,5) | 发射特定整数序列的Observable |
10 | fromArray | Observable.fromArray(arrays) | 遍历数组 |
11 | fromIterable | Observable.fromIterable(list) | 遍历集合 |
12 | toList | Observable.just(1,2,3).toList() | 把数据转换成List集合 |
13 | delay | Observable.create(xxx).delay(3,TimeUnit.SECONDS) | 延迟发送数据 |
14 | onBackpressureDrop | Flowable.interval(1,second).onbackpressureDrop | 超过缓存数量的最大值128之后,直接丢弃掉剩下的内容,除非有新的缓存空间提供 |
15 | onBackpressureBuffer | Flowable.interval(1,Second).onBackpressureBuffer() | 根据需要缓存数据 |
一些例子
create()
create操作符是最常见的,通过该方法创建一个Observable对象(被观察者)
Observable.create(new ObservableOnSubscribe<Integer>(){
@Override
public void subscribe(ObservableEmitter<Integer> emitter) {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
})
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.i("NPL","Disable--"+disposable.isDisposable());
}
@Override
public void onNext(Integer integer) {
Log.i("NPL","onNext---"+integer);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.i("NPL","onComplete");
}
});
需要注意一下几点:
- 在发射3之后,调用onComplete方法,不会再发送数据
- 这里我们多了一个throws Excetion,意味着我们可以做一些特定的操作也不同try-catch
- 这里引入了Disposable概念,这个可以直接用于切断。如果isDisposable返回值为false的时候,接收器能正常接收事件,如果为true,则接收器会停止接收。
Observable.create(new ObservableOnSubscribe<Integer>(){
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","mainThread---"+integer);
}
})
.observeOn(Schedulers.io())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","ioThread---"+integer);
}
});
注意:
- consumer对象完全替代了Observer,效果是一样的。
map()
map操作符也是RxJava中的基本操作符
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
})
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
Log.i("NPL","apply需要处理的数据---"+integer);
return "返回结果是"+integer;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("NPL","accept:"+s+";Thread:"+Thread.currentThread().getName());
}
});
flatMap()
可以把一个发射器Observable通过某种方法转换成多个Observables,然后再把这些分散的Observables装进一个单一的发射器Observable。需要注意的是,flatMap并不能保证时间的顺序
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
})
.flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> datas = new ArrayList<>();
for (int i=0;i<3;i++){
datas.add("value:"+integer);
}
return Observable.fromIterable(datas).delay(3,TimeUnit.SECONDS);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("NPL","accept:"+s);
}
});
concatMap()
与flatMap的使用是相类似的,唯一不同是flatMap是无序的,concatMap是有序的
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
}
})
.concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> data = new ArrayList<>();
for (int i=0;i<4;i++){
data.add("value:"+integer);
}
return Observable.fromIterable(data).delay(4,TimeUnit.SECONDS);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("NPL","accept:"+s);
}
});
zip()
这里我们需要先构建两个发射器,分别操作String类型和Integer类型
//创建String类型发射器
public Observable<String> getStringObservable(){
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("A");
emitter.onNext("B");
emitter.onNext("C");
}
});
}
//创建integer类型发射器
public Observable<Integer> getIntegerObservable(){
return Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
}
});
}
public void funcZip(){
Observable
.zip(getStringObservable(), getIntegerObservable(), new BiFunction<String, Integer, String>() {
@Override
public String apply(String s, Integer integer) throws Exception {
return s+integer;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("NPL","accept:"+s);
}
});
}
需要注意:
- zip组合事件的过程就是分别从发射器A和发射器B去一个事件进行组合,并且一个事件只会被使用一次,组合的顺序是严格按照事件发送顺序来实现的
- 最终接收器收到的事件数量是和发送器发送事件最少的那个的数目相同
interval()
interval操作符是每隔一段时间就产生一个数字,这些数字默认是从0开始,每次递增1至无穷大
public void funcInterval(){
Flowable.interval(2,TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.i("NPL","accept:"+aLong);
}
});
//或者另外一种方式
Observable.interval(3,TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.i("NPL","accept:"+aLong);
}
});
}
这里我们可以利用这个实现一个倒计时的功能
take()
发射这个发送者前n个item
public void funcTake(){
Observable.just(1,2,3,4,5,6,7,8,9,10)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.take(3)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}
repeat()
重复的发送数据,repeat()无限重复,repeat(num)设定重复的次数
public void funcRepeat(){
Observable
.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
})
.repeat(3)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e("NPL","accept:"+integer);
}
});
}
range()
发送特定证书序列的Observable
range(int start,int end)
public void funcRange(){
Observable.range(1,5)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}
fromArray()
遍历数组
public void funcFromArray(){
Integer[] items = {1,2,3,4,5};
Observable.fromArray(items)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e("NPL","accept="+integer);
}
});
}
fromIterable()
遍历集合
public void funcFromIterable(){
List<String> datas = new ArrayList<>();
datas.add("A");
datas.add("B");
datas.add("C");
Observable.fromIterable(datas)
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("NPL","accept:"+s);
}
});
}
toList()
吧数据转换成list集合
public void funcToList(){
Observable.just(1,2,3,4)
.toList().subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
Log.i("NPL","accept:"+integers.toString());
}
});
//把数组转换成list集合
Integer[] items = {1,2,3,4,5,6};
Observable.fromArray(items)
.toList()
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
Log.i("NPL","accept:"+integers.toString());
}
});
}
delay()
延迟发送数据
public void funcDelay(){
Observable.just(1,2,3,4)
.delay(3,TimeUnit.SECONDS)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}
backPressure
背压,产生的原因:被观察者发送消息太快以至于他的操作符或者订阅者不能及时处理相关消息,在RxJava1.x中会报错,是应用程序崩溃
caused by:rx.exceptions.MissingBacjoressureException
为了解决这个问题,RxJava2.x中引入的Flowable类,Observable中不包含背压backpressure处理,而Flowable中包含
我们这里模拟一个触发背压的事例,发射器每隔一毫秒发送一个数据,接收器每个一秒处理一个数据,数据产生是数据处理的1000倍
- Observable的方法来实现
public void backpressure2Observable(){
Observable.interval(1,TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Thread.sleep(1000);
Log.i("NPL","accept:"+aLong);
}
});
}
经过测试,App很健壮,没有发生奔溃,这里的数据由于没有背压,所以全部都缓存到内存中
Observable:
- 不支持backPressure处理,不会发生MissBackPressureException异常
- 所有没有处理的数据都缓存到内存中,等待被订阅者处理
- 当产生的数据过快,内存中的缓存也会越来越多,占用大量内存
- Flowable实现
public void backpressure2Flowable(){
Flowable.interval(1,TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Thread.sleep(1000);
Log.i("NPL","accept:"+aLong);
}
});
}
运行之后发生错误,这里是因为Flowable最多只能保存128条数据缓存,超过之后报错。我们这里可以通过onBackpressureDrop()方法,当缓存达到128时,再来的数据就会被丢弃掉。
public void funcOnBackpressureDrop(){
Flowable.interval(1,TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Thread.sleep(1000);
Log.i("NPL","accept:"+aLong);
}
});
}
除此之外还有向onBackpressureLatest就是只保留最新的事件
onBackpressureBuffer()
默认情况下缓存所有的数据,不会丢失数据,当然可以设置缓存队列大小,但是如果缓存超过审定值就会报错
public void funcOnBackpressureBuffer(){
Flowable.interval(1,TimeUnit.MILLISECONDS)
.onBackpressureBuffer(1000) //设置缓存队列为1000
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Thread.sleep(1000);
Log.i("NPL","accept:"+aLong);
}
});
}
filter()
过滤器,可以过滤一些不符合要求的事件,当被观察者发送的事件过多,观察者只需要一些特定的数据时,则可以进行过滤
public void funcFilter() {
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i = 0; i < 100; i++) {
emitter.onNext(i);
}
}
})
.observeOn(Schedulers.io())
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
if (integer % 3 == 0) {
return true;
} else
return false;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}
sample()
每隔一段时间,都会对从被观察者发送的事件中进行取样,这样会导致大量数据丢失,比较适合特定的场合
public void funcSample(){
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i=0;;i++){
emitter.onNext(i);
}
}
})
.sample(1,TimeUnit.SECONDS)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}
distinct()
可以将重复的对象去除掉
public void funcDistinct(){
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i=0;i<10;i++){
emitter.onNext(i);
}
}
})
.take(3)
// .takeLast(3) //取最后三个
.repeat(3)
.distinct()
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i("NPL","accept:"+integer);
}
});
}