RxJava 之创建操作符

859 阅读5分钟

声明

本系列文章是看书(RxJava 2.x 实战)后的记录,类似读书笔记,非原创

RxJava 的创建操作符主要包括如下内容:

  • just():将一个或多个对象转换成发射这个或这些对象的一个 Observable
  • from():将一个 Iterable、一个 Future 或者一个数组转换成一个 Observable
  • create():使用一个函数从头创建一个 Observable
  • defer():只有当订阅者订阅才创建 Observable,为每个订阅创建一个新的 Observable
  • range():创建一个发射指定范围的整数序列的 Observable
  • interval():创建一个按照给定的时间间隔发射整数序列的 Observable
  • timer():创建一个在给定的延时之后发射单个数据的 Observable
  • empty():创建一个什么都不做直接通知完成的 Observable
  • error():创建一个什么都不做直接通知错误的 Observable
  • never():创建一个不发射任何数据的 Observable

1. create、just 和 from

  1. create 使用一个从头开始创建一个 Observable,可以使用 create 操作符从头开始创建一个 Observable,给这个操作符传递一个接受观察者作为参数,编写这个函数让它的行为表现为一个 Observable——恰当地调用观察者的 onNext、onError 和 onComplete 方法。一个形式正确的有限 Observable 必须尝试调用观察者的 onComplete 或者 onError 一次,而且次后不能再调用观察者的任何其他方法。 RxJava 建议我们在传递给 create 方法的函数时,先检查一下观察者的 isDisposed 状态,以便在没有观察者的时候,让 Observable 停止发射数据,防止运行昂贵的运算。
Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
    if (!emitter.isDisposed()) {
        for (int i = 0; i < 10; i++) {
            emitter.onNext(i);
        }
        emitter.onComplete();
    }
}).subscribe(integer -> System.out.println("next: " + integer),
        throwable -> System.out.println("error: " + throwable.getMessage()),
        () -> System.out.println("Sequence complete."));
  1. just 创建一个发射指定值的 Observable,just 将单个数据转换为发射这个单个数据的 Observable。
Observable.just("hello just").subscribe(System.out::println);

just 类似 from,但是 from 回见数组或 Iterable 的数据取出然后逐个发射,而 just 只是简单的原样发射,将数组或 Iterable当做单个数据。它可以接受一至十个参数,返回一个按参数列表顺序发射这些数据的 Observable。 在 RxJava 2.0 中,如果在 just() 中传入 null,则会抛出一个空指针异常。

  1. from from 可以将其它种类的对象和数据类型转换为 Observable,当使用 Observable 时,如果要处理的数据都可以转换为 Observables,而不是需要混合使用 Observables 和其他类型的数据,会非常方便。 例如,Iterable 可以看成同步的 Observable;Future 可以看成总是只发射单个数据的 Observable。通过显式地将那些数据转换为 Observables,可以像使用 Observable 一样与它们交互。 在 RxJava 中,from 操作符可以将 Future、Iterable 和数组转换成 Observable。对于 Iterable 和数组,产生的 Observable 会发射 Iterable 或数组的每一项。 from 方法有一个可接受两个可选参数的版本,分别制定超时时长和时间单位。如果过了指定的时长,Future 还没有返回一个值,那么这个 Observable 就会发射错误通知并终止。

2. repeat

创建一个发射特定数据重复多次的 Observable,repeat 会重复地发射数据。某些实现允许重复发射某个数据序列,还有一些允许限制重复的次数。repeat 不是创建一个 Observable,而是重复发射原始 Observable 的数据序列,这个序列或许是无限的,或许是通过 repeat(n) 指定重复的次数。

Observable.just("hello world").repeat(3).subscribe(System.out::println);

在 RxJava 2.x 中还有两个跟 repeat 相关的操作符:repeatWhen 和 repeatUtil。

repeatWhen

repeatWhen 不是缓存和重放原始的 Observable 的数据序列,而是有条件地重新订阅和发射原来的 Observable。 将原始 Observable 的终止通知(完成或错误)当做一个 void 数据传递给一个通知处理器,以此来决定是否要重新订阅和发射原来的 Observable。这个通知处理器就像一个 Observable 操作符,接受一个发射 void 通知的 Observable 作为输入,返回一个发射 void 数据(重新订阅和发射 Observable) 或者直接终止(使用 repeatWhen 终止发射数据) 的 Observable。

Observable.range(0, 9).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
    @Override
    public ObservableSource<?> apply(Observable<Object> objectObservable) throws Exception {
        return Observable.timer(10, TimeUnit.SECONDS);
    }
}).subscribe(System.out::println);

try {
    Thread.sleep(12000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

这里会发射 0~9 这几个数据,由于使用了 repeatWhen 操作符,因此在 10s 之后还会再发射一次这些数据。

repeatUntil

repeatUntil 是 RxJava 2.x 新增的操作符,表示直到某个条件就不再重复发射数据。当 BooleanSuppiler 的 getAsBoolean() 返回 false 时,表示重复发射上游的 Observable;当返回 true 时,表示中止重复发射上游的 Observable。

final long startTimeMillis = System.currentTimeMillis();
Observable.interval(500, TimeUnit.MILLISECONDS)
        .take(5)
        .repeatUntil(() -> {
            System.out.println(System.currentTimeMillis() - startTimeMillis > 5000);
            return System.currentTimeMillis() - startTimeMillis > 5000;
        })
        .subscribe(System.out::println);
try {
    Thread.sleep(6000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

3. defer、interval 和 timer

1. defer

直到有观察者订阅时才创建 Observable,并且为每个观察者创建一个全新的 Observable。defer 操作符会一直等待直到观察者订阅它,然后使用 Observable 工厂方法生成一个 Observable。对每个观察者都是这样做,因此尽管每个订阅者都以为自己订阅的是同一个 Observable,但实际上每个订阅者获取的是他们自己单独的数据序列。

Observable<String> observable = Observable.defer(new Callable<ObservableSource<? extends String>>() {
    @Override
    public ObservableSource<? extends String> call() throws Exception {
        return Observable.just("hello world");
    }
});
observable.subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        System.out.println(s);
    }
});

2. interval

创建一个按固定时间间隔发射整数序列的 Observable。interval 操作符返回一个 Observable,它按固定的时间间隔发射一个无线递增的整数序列。interval 接受一个表示时间间隔的参数和一个表示时间单位的参数。interval 默认在 computation 调度器上执行。

Observable.interval(1, TimeUnit.SECONDS)
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                System.out.println(aLong);
            }
        });

3. timer

创建一个 Observable,在一个给定的延迟后发射一个特殊的值。timer 返回一个 Observable,在延迟一段时间后发射一个简单的数字 0。timer 操作符默认在 computation 调度上执行。

Observable.timer(2, TimeUnit.SECONDS)
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                // 2 秒后打印
                System.out.println("hello timer");
            }
        });
try {
    Thread.sleep(10000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

4. 小结

上述所有的创建操作符,不仅 Observable 可以使用,Flowable 等也可以使用。