Android Rxjava3 操作符

682 阅读21分钟

Rxjava3操作符

一、常用操作符

创建操作 Create, Defer, Empty/Never/Throw, From, Interval, Just, Range, Repeat, Start, Timer

变换操作 Buffer, FlatMap, GroupBy, Map, ScanWindow

过滤操作 Debounce, Distinct, ElementAt, Filter, First, IgnoreElements, Last, Sample, Skip, SkipLast, Take, TakeLast

组合操作 And/Then/When, CombineLatest, Join, Merge, StartWith, Switch, Zip

错误处理 CatchRetry

辅助操作 Delay, Do, Materialize/Dematerialize, ObserveOn, Serialize, Subscribe, SubscribeOn,TimeInterval, Timeout, Timestamp, Using

条件和布尔操作 All, Amb, Contains, DefaultIfEmpty, SequenceEqual, SkipUntil, SkipWhile, TakeUntil, TakeWhile

算术和集合操作 Average, Concat, Count, Max, Min, Reduce, Sum

转换操作 To

连接操作 Connect, Publish, RefCount, Replay

反压操作,用于增加特殊的流程控制策略的操作符

二、创建操作符

方法名作用
create()创建最简单的事件流
from()创建事件流,可发送不同类型的数据流
just()创建事件流,可发送多个参数的数据流
defer()创建事件流,可缓存可激活事件流
range()创建事件流,可发送范围内的数据流
interval()创建延时重复的事件流
repeat()创建可重复次数的事件流
timer()创建一次延时的事件流

注意:interval()、timer()、delay()的区别

  • interval():用于创建事件流,周期性重复发送
  • timer():用于创建事件流,延时发送一次
  • delay():用于事件流中,可以延时某次事件流的发送

1、create()

创建Observable最原始的方式,onNext/onComplete/onError方法可完全自由控制。

image.png

2、from()

创建事件流,可发送不同类型的数据流。

image.png

from是一系列方法

image.png

fromArray使用

//数组
String[] srr = {"a","b"};
Observable.fromArray(srr);
//数组
Observable.fromArray(1, 2, 3)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Throwable {
                Log.d(TAG, "打印值:" + integer);
            }
        });
        
//打印的值
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:1
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:2
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:3

fromIterable()为实现Iterable接口的类,如List/Map/Set等集合类

List list = new ArrayList<String>();
list.add("a");
Observable.fromIterable(list);

3、just()

just重载了多个参数数量不同的方法,最大可带10个参数,just实际上同样是调用的fromArray方法;

image.png

Observable.just(1, 2, 3);

4、defer()

defer确保了Observable代码在被订阅后才执行(而不是创建后立即执行)。

image.png

5、range()

以队列的形式发送int值

image.png

//从0开始发送10个值
Observable.range(0, 10).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Throwable {
        Log.d(TAG,"打印值:"+integer);
    }
});

//打印
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:0
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:1
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:2
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:3
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:4
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:5
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:6
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:7
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:8
 17124-17124/com.abc.rxjava3 D/MainActivity: 打印值:9

6、interval()

interval用于定时发送

image.png

//每2秒发个自增整数,从0开始
Observable.interval(2, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
    @Override
    public void accept(Long aLong) throws Throwable {
        Log.d(TAG,"打印值:"+aLong);
    }
});

//打印
20:52:37.313 17701-17733/com.abc.rxjava3 D/MainActivity: 打印值:0
20:52:39.317 17701-17733/com.abc.rxjava3 D/MainActivity: 打印值:1
20:52:41.314 17701-17733/com.abc.rxjava3 D/MainActivity: 打印值:2
20:52:43.314 17701-17733/com.abc.rxjava3 D/MainActivity: 打印值:3
20:52:45.313 17701-17733/com.abc.rxjava3 D/MainActivity: 打印值:4

其他方法

//每2秒发个自增整数,从0开始
Observable.interval(2,TimeUnit.SECONDS);
//延迟1秒后,每2秒发个自增整数,从0开始
Observable.interval(1,2,TimeUnit.SECONDS);
//从0开始发送10个数,延迟1秒开始,每个数间隔2秒
Observable.intervalRange(0,10,1,2,TimeUnit.SECONDS);

7、repeat()

repeat操作符可以重复发送指定次数的某个事件流,repeat操作符默认在trampoline调度器上执行,repeat默认重复次数为Long.MAX_VALUE,可使用重载方法指定次数以及使用repeatUntil指定条件。

image.png

//一直重复
Observable.just(0).repeat();
//重复发送3次
Observable.just(0).repeat(3);
//重复发送,直到符合条件时停止
Observable.just(0).repeatUntil(new BooleanSupplier() {
    @Override
    public boolean getAsBoolean() throws Throwable {
        //默认为false,返回true则重复停止
        return false;
    }
});

8、timer()

timer用于延时发送。

image.png

//延时3秒发送
Observable.timer(3,TimeUnit.SECONDS);

三、过滤操作符

过滤操作符主要是指对数据源进行选择和过滤的常用操作符。

方法名作用
bounce()事件流只发射规定范围时间内的数据项
distinct()事件流只发射不重复的数据项
elementAt()事件流只发射第N个数据项
filter()事件流只发射符合规定函数的数据项
first()事件流只发射第一个数据项
last()事件流只发射最后一项数据项
ignoreElements()忽略事件流的发射,只发射事件流的终止事件
sample()事件流对指定的时间间隔进行数据项的采样
skip()事件流忽略前N个数据项
skipLast()事件流忽略后N个数据项
take()事件流只发射前N个数据项
takeLast()事件流只发射后N个数据项

1、skip / skipLast

可以作用于Flowable,Observable,表示源发射数据前,跳过多少个。skipLast(n)操作表示从流的尾部跳过n个元素。

image.png

//跳过1个源数据发送
Observable.just(0, 1, 2).skip(1).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
21:22:14.068 18280-18280/com.abc.rxjava3 D/MainActivity: 打印值:1
21:22:14.068 18280-18280/com.abc.rxjava3 D/MainActivity: 打印值:2

2、debounce(去抖动)

image.png

可作用于Flowable,Observable。在Android开发,通常为了防止用户重复点击而设置标记位,而通过RxJava的debounce操作符可以有效达到该效果。在规定时间内,用户重复点击只有最后一次有效:

        Observable<String> source = Observable.create(emitter -> {
            emitter.onNext("A");
 
            Thread.sleep(1_500);
            emitter.onNext("B");
 
            Thread.sleep(500);
            emitter.onNext("C");
 
            Thread.sleep(250);
            emitter.onNext("D");
 
            Thread.sleep(2000);
            emitter.onNext("E");
            emitter.onComplete();
        });
 
        source.subscribeOn(Schedulers.io())
                .debounce(1, TimeUnit.SECONDS)
                .blockingSubscribe(
                        item ->   Log.w("TAG","onNext--->"+ item),
                        Throwable::printStackTrace,
                        () -> Log.w("TAG","onNext--->"+ "onComplete" ));
 
//结果
2020-04-03 16:08:47.520 30559-30559/com.ysalliance.getfan.myapplication W/TAG: onNext--->A
2020-04-03 16:08:49.777 30559-30559/com.ysalliance.getfan.myapplication W/TAG: onNext--->D
2020-04-03 16:08:50.776 30559-30559/com.ysalliance.getfan.myapplication W/TAG: onNext--->E
2020-04-03 16:08:50.776 30559-30559/com.ysalliance.getfan.myapplication W/TAG: onNext--->onComplete

上文代码中,数据源以一定的时间间隔发送A,B,C,D,E。操作符debounce的时间设为1秒,发送A后1.5秒并没有发射其他数据,所以A能成功发射。发射B后,在1秒之内,又发射了C和D,在D之后的2秒才发射E,所有B、C都失效,只有D有效;而E之后已经没有其他数据流了,所有E有效。

image.png

3、distinct(去重)

可作用于Flowable,Observable,去掉数据源重复的数据。

distinctUntilChanged()去掉相邻重复数据。

image.png

//去掉数据源重复数据
Observable.just(0, 1, 0, 2).distinct().subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
21:32:28.183 18523-18523/com.abc.rxjava3 D/MainActivity: 打印值:0
21:32:28.183 18523-18523/com.abc.rxjava3 D/MainActivity: 打印值:1
21:32:28.183 18523-18523/com.abc.rxjava3 D/MainActivity: 打印值:2


//去掉数据源相邻重复数据
Observable.just(0, 0, 1, 0, 2).distinctUntilChanged().subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
21:34:21.063 18677-18677/com.abc.rxjava3 D/MainActivity: 打印值:0
21:34:21.063 18677-18677/com.abc.rxjava3 D/MainActivity: 打印值:1
21:34:21.063 18677-18677/com.abc.rxjava3 D/MainActivity: 打印值:0
21:34:21.063 18677-18677/com.abc.rxjava3 D/MainActivity: 打印值:2

4、elementAt(获取指定位置元素)

可作用于Flowable,Observable,从数据源获取指定位置的元素,从0开始。

elementAtOrError:指定位置超过数据源长度,则发射异常。

image.png

//获取指定位置的元素
Observable.just(0, 1, 2).elementAt(1).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
21:43:54.120 19158-19158/com.abc.rxjava3 D/MainActivity: 打印值:1


//获取指定位置的元素或发射异常
Observable.just(0, 1, 2).elementAtOrError(4).subscribe(new SingleObserver<Integer>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onSuccess(@NonNull Integer integer) {
        Log.d(TAG, "打印值:integer:" + integer);
    }

    @Override
    public void onError(@NonNull Throwable e) {
        Log.d(TAG, "打印值:throwable:" + LogHelper.getStackTraceAsString(e));
    }
});

//打印
21:50:35.480 19327-19327/com.abc.rxjava3 D/MainActivity: 打印值:throwable:java.util.NoSuchElementException
        at io.reactivex.rxjava3.internal.operators.observable.ObservableElementAtSingle$ElementAtObserver.onComplete(ObservableElementAtSingle.java:115)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableFromArray$FromArrayDisposable.run(ObservableFromArray.java:112)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableFromArray.subscribeActual(ObservableFromArray.java:38)
        at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13095)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableElementAtSingle.subscribeActual(ObservableElementAtSingle.java:37)
        at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
        at com.abc.rxjava3.MainActivity.initRxjava(MainActivity.java:41)
        at com.abc.rxjava3.MainActivity.onCreate(MainActivity.java:29)
        ...省略...
        
//打印异常栈的方法:LogHelper.getStackTraceAsString(e)
public class LogHelper {
    /**
     * 转换异常栈
     * @param throwable
     * @return
     */
    public static String getStackTraceAsString(Throwable throwable) {
        StringWriter writer = new StringWriter();
        throwable.printStackTrace(new PrintWriter(writer));
        return writer.toString();
    }
}

5、filter(过滤)

可作用于 Flowable,Observable,Maybe,Single。在filter中设定过滤条件,返回true表示发射该元素,返回false表示过滤该数据。

image.png

//按过滤条件筛选
Observable.just(0, 1, 2).filter(new Predicate<Integer>() {
    @Override
    public boolean test(Integer integer) throws Throwable {
        if (integer % 2 == 0) {
            return true;
        }
        return false;
    }
}).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
21:58:24.509 19512-19512/com.abc.rxjava3 D/MainActivity: 打印值:0
21:58:24.509 19512-19512/com.abc.rxjava3 D/MainActivity: 打印值:2

6、first(第一个)

作用于 Flowable,Observable。发射数据源第一个数据,如果没有则发送默认值。

image.png

first和firstElement的区别是first返回的是Single,而firstElement返回Maybe。firstOrError在没有数据会返回异常。

//发射数据源中期待值的第一个,没有则发射数据源第一个
Observable.just("a", "b").first("c").subscribe(i -> Log.d(TAG, "打印值:" + i));
//打印
22:10:49.019 20123-20123/com.abc.rxjava3 D/MainActivity: 打印值:a

//发射数据源中第一个
Observable.just("a", "b").firstElement().subscribe(i -> Log.d(TAG, "打印值:" + i));
//打印
22:10:49.019 20123-20123/com.abc.rxjava3 D/MainActivity: 打印值:a

//发射数据源第一个或error
Observable.empty().firstOrError().subscribe(new SingleObserver<Object>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onSuccess(@NonNull Object o) {

    }

    @Override
    public void onError(@NonNull Throwable e) {
        Log.d(TAG,"打印:"+LogHelper.getStackTraceAsString(e));
    }
});
//打印
22:15:57.552 20519-20519/com.abc.rxjava3 D/MainActivity: 打印:java.util.NoSuchElementException
        at io.reactivex.rxjava3.internal.operators.observable.ObservableElementAtSingle$ElementAtObserver.onComplete(ObservableElementAtSingle.java:115)
        at io.reactivex.rxjava3.internal.disposables.EmptyDisposable.complete(EmptyDisposable.java:53)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableEmpty.subscribeActual(ObservableEmpty.java:27)
        at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13095)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableElementAtSingle.subscribeActual(ObservableElementAtSingle.java:37)
        at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
        at com.abc.rxjava3.MainActivity.initRxjava(MainActivity.java:39)
        ...省略...

7、last(最后一个)

last、lastElement、lastOrError与fist、firstElement、firstOrError相对应。

image.png

8、ignoreElements & ignoreElement(忽略元素)

ignoreElements 作用于Flowable、Observable。ignoreElement作用于Maybe、Single。两者都是忽略掉数据,不发射任何数据,返回完成或者错误时间。

image.png

//延迟1秒发射数据源
Single.timer(1,TimeUnit.SECONDS).ignoreElement().subscribe(new CompletableObserver() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete");
    }

    @Override
    public void onError(@NonNull Throwable e) {
        Log.d(TAG, "onError:" + LogHelper.getStackTraceAsString(e));
    }
});

//延时1秒后打印
22:28:14.938 20850-20880/com.abc.rxjava3 D/MainActivity: onComplete


//延时0秒,间隔1秒,从0开始发送5次数据
Observable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS).ignoreElements().subscribe(new CompletableObserver() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {

    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete");
    }

    @Override
    public void onError(@NonNull Throwable e) {
        Log.d(TAG, "onError:" + LogHelper.getStackTraceAsString(e));
    }
});

//延时5秒后打印
22:34:25.909 21127-21158/com.abc.rxjava3 D/MainActivity: onComplete

9、ofType(过滤类型)

作用于Flowable、Observable、Maybe,过滤选择类型。

//过滤指定的类型的数据
Observable.just(0, 1.0f, 1).ofType(Float.class).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
2:39:20.605 21591-21591/com.abc.rxjava3 D/MainActivity: 打印值:1.0

10、sample

作用于Flowable、Observable,在一个周期内发射最新的数据。sample操作符会在指定的事件内从数据项中采集所需要的数据。

image.png

Observable<String> source = Observable.create(emitter -> {
    emitter.onNext("A");
 
    Thread.sleep(500);
    emitter.onNext("B");
 
    Thread.sleep(200);
    emitter.onNext("C");
 
    Thread.sleep(800);
    emitter.onNext("D");
 
    Thread.sleep(600);
    emitter.onNext("E");
    emitter.onComplete();
});
 
source.subscribeOn(Schedulers.io())
        .sample(1, TimeUnit.SECONDS)
        .blockingSubscribe(
                item -> System.out.print(item+" "),
                Throwable::printStackTrace,
                () -> System.out.print("onComplete"));
                
// 打印: C D onComplete

与debounce的区别是,sample是以时间为周期的发射,一秒又一秒内的最新数据。而debounce是最后一个有效数据开始。

image.png

11、take & takeLast

作用于Flowable、Observable。take发射前n个元素。takeLast发射后n个元素。

image.png

//发射前3个元素(同时,方法回调3次)
Observable.just(0, 1, 2, 3).take(3).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印(方法回调的时间相同)
22:47:01.104 21899-21899/com.abc.rxjava3 D/MainActivity: 打印值:0
22:47:01.104 21899-21899/com.abc.rxjava3 D/MainActivity: 打印值:1
22:47:01.104 21899-21899/com.abc.rxjava3 D/MainActivity: 打印值:2

12、timeout(超时)

作用于Flowable、Observable、Maybe、Single、Completabl。后一个数据发射未在前一个元素发射后规定时间内发射则返回超时异常。

//timeout
Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
        emitter.onNext(0);
        SystemClock.sleep(1500);
        emitter.onNext(1);
    }
}).timeout(1, TimeUnit.SECONDS)
        .subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                Log.d(TAG, "onSubscribe");
            }

            @Override
            public void onNext(@NonNull Integer integer) {
                Log.d(TAG, "onNext:"+integer);
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Log.d(TAG, "onError:"+LogHelper.getStackTraceAsString(e));
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete");
            }
        });
        
//打印
22:56:06.513 22262-22262/com.abc.rxjava3 D/MainActivity: onSubscribe
22:56:06.515 22262-22262/com.abc.rxjava3 D/MainActivity: onNext:0
22:56:07.516 22262-22294/com.abc.rxjava3 D/MainActivity: onError:java.util.concurrent.TimeoutException: The source did not signal an event for 1 seconds and has been terminated.
        at io.reactivex.rxjava3.internal.operators.observable.ObservableTimeoutTimed$TimeoutObserver.onTimeout(ObservableTimeoutTimed.java:134)
        at io.reactivex.rxjava3.internal.operators.observable.ObservableTimeoutTimed$TimeoutTask.run(ObservableTimeoutTimed.java:165)
        at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
        at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
        ...省略...
        

13、merge/concat(合并)

merge操作符可以合并两个事件流,如果在merge操作符上增加延时发送的操作,那么就会导致其发射的数据项是无序的,会跟着发射的时间点进行合并。虽然是将两个事件流合并成一个事件流进行发射,但在最终的一个事件流中,发射出来的却是两次数据流。

merge和concat的区别:merge():合并后发射的数据项是无序的​​​​​​,concat():合并后发射的数据项是有序的。

image.png

//merge
Observable<Integer> integerObservable0 = Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
        SystemClock.sleep(1500);
        emitter.onNext(0);
    }
});

Observable<Integer> integerObservable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
        emitter.onNext(1);
        SystemClock.sleep(2000);
        emitter.onNext(2);
    }
});

Observable.merge(integerObservable0, integerObservable1).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Throwable {
        Log.d(TAG, "打印值:" + integer);
    }
});

//打印(注意打印的时间,有合并)
23:09:16.279 22865-22865/com.abc.rxjava3 D/MainActivity: 打印值:0
23:09:16.279 22865-22865/com.abc.rxjava3 D/MainActivity: 打印值:1
23:09:18.283 22865-22865/com.abc.rxjava3 D/MainActivity: 打印值:2
//concat
Observable<Integer> integerObservable0 = Observable.just(0, 1);
Observable<Integer> integerObservable1 = Observable.just(2, 3);

Observable.concat(integerObservable0, integerObservable1).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Throwable {
        Log.d(TAG, "打印值:" + integer);
    }
});

//打印(时间是同样的)
23:15:28.765 23169-23169/com.abc.rxjava3 D/MainActivity: 打印值:0
23:15:28.765 23169-23169/com.abc.rxjava3 D/MainActivity: 打印值:1
23:15:28.765 23169-23169/com.abc.rxjava3 D/MainActivity: 打印值:2
23:15:28.765 23169-23169/com.abc.rxjava3 D/MainActivity: 打印值:3

14、zip(拉链)

zip操作符是将两个数据流进行指定的函数规则合并。当其中一个数据源发射完事件之后,若其他数据源还有数据未发射完毕,也会停止。

image.png

//zip
Observable<String> integerObservable0 = Observable.just("A", "C");
Observable<Integer> integerObservable1 = Observable.just(1, 3);

Observable.zip(integerObservable0, integerObservable1, new BiFunction<String, Integer, String>() {
    @Override
    public String apply(String str, Integer integer) throws Throwable {
        return str + integer;
    }
}).subscribe(new Consumer<String>() {
    @Override
    public void accept(String value) throws Throwable {
        Log.d(TAG, "打印值:" + value);
    }
});

//打印
23:28:59.328 23666-23666/com.abc.rxjava3 D/MainActivity: 打印值:A1
23:28:59.328 23666-23666/com.abc.rxjava3 D/MainActivity: 打印值:C3

15、startWith()

startWith操作符是将另一个数据流合并到原数据流的开头。

image.png

//startWith
Observable<Integer> integerObservable0 = Observable.just(2, 3);
Observable<Integer> integerObservable1 = Observable.just(0, 1);

integerObservable0.startWith(integerObservable1).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Throwable {
        Log.d(TAG, "打印值:" + integer);
    }
});

//打印
23:33:10.743 23842-23842/com.abc.rxjava3 D/MainActivity: 打印值:0
23:33:10.743 23842-23842/com.abc.rxjava3 D/MainActivity: 打印值:1
23:33:10.744 23842-23842/com.abc.rxjava3 D/MainActivity: 打印值:2
23:33:10.744 23842-23842/com.abc.rxjava3 D/MainActivity: 打印值:3

四、连接/组合操作符

1、combineLatest()

可作用于Flowable, Observable。在结合不同数据源时,发射速度快的数据源最新item与较慢的相结合。

image.png

//combineLatest
Observable<Long> longObservable = Observable.interval(1, TimeUnit.SECONDS);

Observable<String> stringObservable = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
        emitter.onNext("A");
        SystemClock.sleep(1000);
        emitter.onNext("B");
        SystemClock.sleep(2000);
        emitter.onNext("C");
        emitter.onComplete();
    }
});

Observable.combineLatest(longObservable, stringObservable, new BiFunction<Long,String, String>() {
    @Override
    public String apply( Long aLong,String s) throws Throwable {
        return s + aLong;
    }
}).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
10:27:38.781 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:A0
10:27:38.781 29551-29551/com.abc.rxjava3 D/MainActivity: 打印值:B0
10:27:39.781 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:B1
10:27:40.784 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:B2
10:27:40.785 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C2
10:27:41.783 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C3
10:27:42.783 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C4
10:27:43.785 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C5
10:27:44.786 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C6
10:27:45.786 29551-29582/com.abc.rxjava3 D/MainActivity: 打印值:C7
...省略C8,C9等等...

2、switchOnNext()

一个发射多个小数据源的数据源,这些小数据源发射数据的时间发生重复时,取最新的数据源。

image.png

五、变换/转换操作符

变换操作符用于变化数据源的数据,并转化为新的数据源。

操作符作用
map()对数据流的类型进行转换
flatMap()对数据流的类型进行包装成另一个数据流
scan()对上一轮处理过后的数据流进行函数处理
groupBy()对所有的数据流进行分组
buffer()缓存发射的数据流到一定数量,随后发射出数据流集合
window()缓存发射的数据流到一定数量,随后发射出新的事件流

1、map()

对数据源进行类型转换。

image.png

//map
Observable.interval(1, TimeUnit.SECONDS).map(new Function<Long, Long>() {
    @Override
    public Long apply(Long aLong) throws Throwable {
        //取偶数
        return aLong << 1;
    }
}).subscribe(s -> Log.d(TAG, "打印值:" + s));

//打印
10:44:33.544 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:0
10:44:34.544 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:2
10:44:35.546 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:4
10:44:36.545 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:6
10:44:37.544 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:8
10:44:38.545 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:10
10:44:39.544 30098-30126/com.abc.rxjava3 D/MainActivity: 打印值:12
...省略...

2、flatMap() / concatMap()

flatMap/concatMap操作符将数据流(ObservableSource)进行类型转换,然后将新的数据流(ObservableSource)传递给新的事件流进行分发。
concatMap与flatMap的区别:    concatMap是有序的,flatMap是无序的。见下图。

image.png

//flatMap
Observable.interval(1, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<?>>() {
    @Override
    public ObservableSource<?> apply(Long aLong) throws Throwable {
        return  Observable.just(aLong);
    }
}).subscribe(i -> Log.d(TAG, "打印值:" + i));

//打印
11:23:34.265 30838-30903/com.abc.rxjava3 D/MainActivity: 打印值:0
11:23:35.265 30838-30903/com.abc.rxjava3 D/MainActivity: 打印值:1
11:23:36.268 30838-30903/com.abc.rxjava3 D/MainActivity: 打印值:2
11:23:37.267 30838-30903/com.abc.rxjava3 D/MainActivity: 打印值:3
11:23:38.267 30838-30903/com.abc.rxjava3 D/MainActivity: 打印值:4
...省略...

3、groupBy()

groupBy操作符可以将发射出来的数据项进行分组,并将分组后的数据项保存在具有key-value映射的事件流中。groupBy具体的分组规则由groupBy操作符传递进来的函数参数Function所决定的,它可以将key和value按照Function的返回值进行分组,返回一个具有分组规则的事件流GroupedObservable,注意这里分组出来的事件流是按照原始事件流的顺序输出的,我们可以通过sorted()对数据项进行排序,然后输出有序的数据流。

image.png

//groupBy
Observable.just(3, 2, 1, 0)
        .groupBy(new Function<Integer, Boolean>() {
            @Override
            public Boolean apply(Integer integer) throws Throwable {
                return integer % 2 == 0;   //方法的返回值为key,也是以key为分组标准
            }
        }).subscribe(new Consumer<GroupedObservable<Boolean, Integer>>() {
    @Override
    public void accept(GroupedObservable<Boolean, Integer> groupedObservable) throws Throwable {
        groupedObservable
                .sorted()   //排序
                .subscribe(
                i -> Log.d(TAG, "打印值:key:" + groupedObservable.getKey() + ",value:" + i)
        );
    }
});

//打印
13:06:38.988 32608-32608/com.abc.rxjava3 D/MainActivity: 打印值:key:false,value:1
13:06:38.988 32608-32608/com.abc.rxjava3 D/MainActivity: 打印值:key:false,value:3
13:06:38.988 32608-32608/com.abc.rxjava3 D/MainActivity: 打印值:key:true,value:0
13:06:38.988 32608-32608/com.abc.rxjava3 D/MainActivity: 打印值:key:true,value:2

4、scan()

scan操作符会对发射的数据和上一轮发射的数据进行函数处理,并返回的数据供下一轮使用,持续这个过程来产生剩余的数据流。其应用场景有简单的累加计算,判断所有数据的最小值等。

image.png

//scan
Observable.just(1, 2, 0, -1, 3)
        //.scan((integer0, integer1) -> integer0 + integer1)  //求和
        .scan((integer0, integer1) -> integer0 > integer1 ? integer1 : integer0)  //扫描过程中不断取最小值
        .subscribe(i -> Log.d(TAG, "打印值:" + i));
        
//打印
13:46:43.384 3129-3129/com.abc.rxjava3 D/MainActivity: 打印值:1
13:46:43.384 3129-3129/com.abc.rxjava3 D/MainActivity: 打印值:1
13:46:43.384 3129-3129/com.abc.rxjava3 D/MainActivity: 打印值:0
13:46:43.384 3129-3129/com.abc.rxjava3 D/MainActivity: 打印值:-1
13:46:43.384 3129-3129/com.abc.rxjava3 D/MainActivity: 打印值:-1

5、buffer()

buffer操作符可以将发射出来的数据流,在给定的缓存池中进行缓存,当缓存池中的数据项溢满时,则将缓存池的数据项进行输出,重复上述过程,直到将发射出来的数据全部发射出去。如果发射出来的数据不够缓存池的大小,则按照当前发射出来的数量进行输出。如果对buffer操作符设置了skip参数,则buffer每次缓存池溢满时,会跳过指定的skip数据项,然后再进行缓存和输出。

image.png

//buffer
Observable.just(0, 1, 2, 3, 4)
        .buffer(2)  //缓存池大小
        .subscribe(list -> Log.d(TAG, "打印值:" + list.toString()));
        
//打印
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[0, 1]
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[2, 3]
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[4]

6、window()

window操作符和buffer操作符在功能上实现的效果是一样的,但window操作符最大区别在于同样是缓存一定数量的数据项,window操作符最终发射出来的是新的事件流integerObservable,而buffer操作符发射出来的是新的数据流,也就是说,window操作符发射出来新的事件流中的数据项,还可以经过Rxjava其他操作符进行处理。

image.png

//window
Observable.just(0, 1, 2, 3, 4)
        .window(2, 1)  //缓存池大小2,skip(跳跃走)为1
        .subscribe(observable -> observable.subscribe(
                list -> Log.d(TAG, "打印值:" + list.toString())));
                
//打印
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[0, 1]
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[2, 3]
13:53:20.729 3420-3420/com.abc.rxjava3 D/MainActivity: 打印值:[4]

7、cast()

作用于Flowable、Observable、Maybe、Single。将数据元素转型成其他类型,转型失败会抛出异常。

//cast
Observable.just(0, 1.0f,"A",2)
        .filter(value -> Integer.class.isInstance(value))  //筛选Integer
        .cast(Integer.class)   //不能将Integer转成String,这里一般是做强制类型转换
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Throwable {
                Log.d(TAG, "打印值:" + integer);
            }
        });
        
//打印
14:57:40.671 5497-5497/com.abc.rxjava3 D/MainActivity: 打印值:0
14:57:40.671 5497-5497/com.abc.rxjava3 D/MainActivity: 打印值:2
//Person接口
public interface Person {
    String setName(String name);
}

//Student实现类
public class Student implements Person {

    @Override
    public String setName(String name) {
        return name;
    }
}

//cast
Student student = new Student();
Observable.just(student)
        .cast(Person.class)   //这里一般是做强制类型转换
        .subscribe(new Consumer<Person>() {
            @Override
            public void accept(Person person) throws Throwable {
                Log.d(TAG, "打印值:" + person.setName("ZhangSan"));
            }
        });
        
//打印
15:01:08.838 5647-5647/com.abc.rxjava3 D/MainActivity: 打印值:ZhangSan

8、flattenAsFlowable & flattenAsObservable

作用于Maybe、Single,将其转化为Flowable,或Observable。

六、处理操作符

操作符作用
onErrorReturn()当错误发生时,它会忽略onError的回调且会发射一个新的数据项并回调onCompleted()
onErrorResumeNext()当错误发生时,它会忽略onError的回调且会发射一个新的事件流并回调onCompleted()
onExceptionResumeNext()当错误发生时,如果onError收到的Throwable不是一个Exception,它会回调onError方法,且不会回调备用的事件流,如果onError收到的Throwable是一个Exception,它会回调备用的事件流进行数据的发射
retry()当错误发生时,发射器会重新发射
retryWhen()当错误发生时,根据Tharowble类型决定发射器是否重新发射

1、onErrorReturn()

作用于Flowable、Observable、Maybe、Single。但调用数据源的onError函数后会回到该函数,可对错误进行处理,然后返回值,会调用观察者onNext()继续执行,执行完调用onComplete()函数结束所有事件的发射。

image.png

//onErrorReturn
Single.just('A')
        .map(c->Integer.parseInt(c.toString()))  //char转int失败
        .onErrorReturn(new Function<Throwable, Integer>() {
            @Override
            public Integer apply(Throwable throwable) throws Throwable {
                return (int)'A';  //返回char的ASCII码值
            }
        })
        .subscribe(v->Log.d(TAG, "打印值:" + v));
        
//打印
15:20:56.595 5938-5938/com.abc.rxjava3 D/MainActivity: 打印值:65

2、onErrorReturnItem()

与onErrorReturn类似,onErrorReturnItem不对错误进行处理,直接返回一个值。

3、onExceptionResumeNext()

可作用于Flowable、Observable、Maybe。

onErrorReturn发生异常时,回调onComplete()函数后不再往下执行,而onExceptionResumeNext则是要在处理异常的时候返回一个数据源,然后继续执行,如果返回null,则调用观察者的onError()函数。

image.png

//onErrorResumeNext
Observable.create((ObservableOnSubscribe<Integer>) e -> {
    e.onNext(1);
    e.onNext(2);
    e.onError(new NullPointerException());
}).onErrorResumeNext(throwable -> {
    Log.d(TAG, "onErrorResumeNext ");
    //return Observable.just(3);
    return null;
}).subscribe(new Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.d(TAG, "onSubscribe ");
    }

    @Override
    public void onNext(Integer integer) {
        Log.d(TAG, "onNext " + integer);
    }

    @Override
    public void onError(Throwable e) {
        Log.d(TAG, "onError: "+LogHelper.getStackTraceAsString(e));
    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete ");
    }
});

//打印
15:31:15.635 7098-7098/com.abc.rxjava3 D/MainActivity: onSubscribe 
15:31:15.636 7098-7098/com.abc.rxjava3 D/MainActivity: onNext 1
15:31:15.636 7098-7098/com.abc.rxjava3 D/MainActivity: onNext 2
15:31:15.636 7098-7098/com.abc.rxjava3 D/MainActivity: onErrorResumeNext 
15:31:15.638 7098-7098/com.abc.rxjava3 D/MainActivity: onError: java.lang.NullPointerException: Observable is null

4、retry()

可作用于所有的数据源,当发生错误时,数据源重复发射item,直到没有异常或者达到所指定的次数。

image.png

boolean isRetry = true;
Observable.create((ObservableOnSubscribe<Integer>) e -> {
    e.onNext(1);
    e.onNext(2);
    if (isRetry) {
        e.onError(new NullPointerException());
    } else {
        e.onNext(3);
    }
}).retry(2, new Predicate<Throwable>() {
    @Override
    public boolean test(Throwable throwable) throws Throwable {
        Log.d(TAG, "test ");
        isRetry = false;
        return true;  //默认返回false不重试
    }
}).subscribe(new Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.d(TAG, "onSubscribe ");
    }

    @Override
    public void onNext(Integer integer) {
        Log.d(TAG, "onNext " + integer);
    }

    @Override
    public void onError(Throwable e) {
        Log.d(TAG, "onError: " + LogHelper.getStackTraceAsString(e));
    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete ");
    }
});

//打印
15:43:15.090 7610-7610/com.abc.rxjava3 D/MainActivity: onSubscribe 
15:43:15.090 7610-7610/com.abc.rxjava3 D/MainActivity: onNext 1
15:43:15.090 7610-7610/com.abc.rxjava3 D/MainActivity: onNext 2
15:43:15.091 7610-7610/com.abc.rxjava3 D/MainActivity: test 
15:43:15.091 7610-7610/com.abc.rxjava3 D/MainActivity: onNext 1
15:43:15.091 7610-7610/com.abc.rxjava3 D/MainActivity: onNext 2
15:43:15.091 7610-7610/com.abc.rxjava3 D/MainActivity: onNext 3

5、retryUntil()

作用于Flowable、Observable、Maybe。与retry类似,但发生异常时,返回值是false表示继续执行(重复发射数据),true不再执行,但会调用onError方法。

//retryUntil
Observable.create((ObservableOnSubscribe<Integer>) e -> {
    e.onNext(1);
    e.onNext(2);
    e.onError(new NullPointerException());
}).retryUntil(() -> true)
        .subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe ");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "onNext " + integer);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: " + LogHelper.getStackTraceAsString(e));
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete ");
            }
        });
        
//打印
15:55:23.962 7834-7834/com.abc.rxjava3 D/MainActivity: onSubscribe 
15:55:23.963 7834-7834/com.abc.rxjava3 D/MainActivity: onNext 1
15:55:23.963 7834-7834/com.abc.rxjava3 D/MainActivity: onNext 2
15:55:23.965 7834-7834/com.abc.rxjava3 D/MainActivity: onError: java.lang.NullPointerException

6、retryWhen()

retryWhen操作符和retry操作符相似,区别在于retryWhen将错误Throwable传递给了函数进行处理并产生新的事件流进行处理。

image.png

参考了以下文章,表示感谢:

Rxjava3文档级教程二: 操作符全解

--个人学习笔记