RxJava操作符——辅助操作符(Observable Utility Operators)

RxJava系列教程:

1. RxJava使用介绍 【视频教程】
2. RxJava操作符
  • Creating Observables(Observable的创建操作符) 【视频教程】
  • Transforming Observables(Observable的转换操作符) 【视频教程】
  • Filtering Observables(Observable的过滤操作符) 【视频教程】
  • Combining Observables(Observable的组合操作符) 【视频教程】
  • Error Handling Operators(Observable的错误处理操作符) 【视频教程】
  • Observable Utility Operators(Observable的辅助性操作符) 【视频教程】
  • Conditional and Boolean Operators(Observable的条件和布尔操作符) 【视频教程】
  • Mathematical and Aggregate Operators(Observable数学运算及聚合操作符) 【视频教程】
  • 其他如observable.toList()、observable.connect()、observable.publish()等等; 【视频教程】
3. RxJava Observer与Subcriber的关系 【视频教程】
4. RxJava线程控制(Scheduler) 【视频教程】
5. RxJava 并发之数据流发射太快如何办(背压(Backpressure)) 【视频教程】


Delay

delay的意思就是延迟,这个操作符会延迟一段指定的时间再发射Observable的数据。 RxJava的实现是 delay和delaySubscription。

delay:让原始Observable在发射每项数据之前都暂停一段指定的时间段,结果是Observable发射的数据项在时间上整体延后一段时间。

注意:delay不会平移onError通知,它会立即将这个通知传递给订阅者,同时丢弃任何待发射的onNext通知。但是它会平移一个onCompleted通知。
    
这里写图片描述    

delaySubscription:和delay不同的是,delaySubscription是延迟订阅原始Observable,这样也能达到数据延迟发射的效果。
这里写图片描述

示例代码:

Observable<Long> observable = Observable.interval(1, TimeUnit.SECONDS).take(5);
/*
 * Delay操作符让原始Observable在发射每项数据之前都暂停一段指定的时间段。
 * 效果是Observable发射的数据项在时间上向前整体平移了一个增量
 *
 * 注意:delay不会平移onError通知,它会立即将这个通知传递给订阅者,同时丢弃任何待发射的onNext通知。
 * 然而它会平移一个onCompleted通知。
 */
observable
        .delay(3, TimeUnit.SECONDS)
        .subscribe(new Subscriber<Long>() {
            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
            }
            @Override
            public void onError(Throwable e) {
                System.out.println("onError");
            }
            @Override
            public void onNext(Long value) {
                System.out.println("delay onNext value :"+ value);
            }
        });

/*
 * delaySubscription:延迟订阅原始Observable
 */
observable
        .delaySubscription(3, TimeUnit.SECONDS)
             .subscribe(new Subscriber<Long>() {
                 @Override
                 public void onCompleted() {
                     System.out.println("onCompleted");
                 }
                 @Override
                 public void onError(Throwable e) {
                    System.out.println("onError");
                 }
                 @Override
                 public void onNext(Long value) {
                    System.out.println("delaySubscription onNext value :"+ value);
                 }
             });

输出:

delay onNext value :0
delay onNext value :1
delay onNext value :2
delay onNext value :3
delay onNext value :4
onCompleted

delaySubscription onNext value :0
delaySubscription onNext value :1
delaySubscription onNext value :2
delaySubscription onNext value :3
delaySubscription onNext value :4
onCompleted

Do

Do系列操作符就是为原始Observable的生命周期事件注册一个回调,当Observable的某个事件发生时就会调用这些回调。RxJava实现了很多doxxx操作符:
这里写图片描述  

  • doOnEach:为 Observable注册这样一个回调,当Observable没发射一项数据就会调用它一次,包括onNext、onError和 onCompleted
  • doOnNext:只有执行onNext的时候会被调用
  • doOnSubscribe: 当观察者(Sunscriber)订阅Observable时就会被调用
  • doOnUnsubscribe: 当观察者取消订阅Observable时就会被调用;Observable通过onError或者onCompleted结束时,会反订阅所有的Subscriber
  • doOnCompleted:当Observable 正常终止调用onCompleted时会被调用。
  • doOnError: 当Observable 异常终止调用onError时会被调用。
  • doOnTerminate: 当Observable 终止之前会被调用,无论是正常还是异常终止
  • finallyDo: 当Observable 终止之后会被调用,无论是正常还是异常终止。

示例代码:

Observable.just(1,2,3,4,5,6)
        .doOnEach(new Action1<Notification<? super Integer>>() {

            @Override
            public void call(Notification<? super Integer> t) {
                System.out.println("doOnEach value = " + t.getValue());
            }
        })
        .doOnError(new Action1<Throwable>() {

            @Override
            public void call(Throwable t) {
                System.out.println("doOnError " + t);

            }
        })
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("onError: " + e.getMessage());
            }

            @Override
            public void onNext(Integer integer) {
                System.out.println("onNext: " + integer);
            }
        });

输出:

doOnSubscribe
doOnEach value = 1
onNext: 1
doOnEach value = 2
onNext: 2
doOnEach value = 3
onNext: 3
doOnEach value = 4
onNext: 4
doOnEach value = 5
onNext: 5
doOnEach value = 6
onNext: 6
doOnEach value = null
doOnCompleted
onCompleted
doAfterTerminate

Materialize/Dematerialize

materialize将来自原始Observable的通知(onNext/onError/onComplete)都转换为一个Notification对象,然后再按原来的顺序一次发射出去。
Dematerialize操作符是Materialize的逆向过程,它将Materialize转换的结果还原成它原本的形式( 将Notification对象还原成Observable的通知)
这里写图片描述  

示例代码:

Observable.just(1,2,3,4,5,6).materialize()
        .subscribe(new Action1<Notification>() {

            @Override
            public void call(Notification t) {
                //这里,onComplete也被meterialize包装后发射了出来,onError也同样。
                System.out.println("meterialize:" + t.getValue() + "   type " + t.getKind());               
            }
        });
        System.out.println("-------------------------");    

        //将Notification逆转为普通消息发射
        Observable<Integer> observable = Observable.just(1,2,3,4,5,6).materialize().dematerialize();
        observable.subscribe(new Action1<Integer>() {

            @Override
            public void call(Integer value) {
                System.out.println("onNext: " + value);
            }
        });

输出:

meterialize:1   type OnNext
meterialize:2   type OnNext
meterialize:3   type OnNext
meterialize:4   type OnNext
meterialize:5   type OnNext
meterialize:6   type OnNext
meterialize:null   type OnCompleted
-------------------------
onNext: 1
onNext: 2
onNext: 3
onNext: 4
onNext: 5
onNext: 6

ObserveOn/SubscribeOn

这两个操作符对于Android开发来说非常适用,因为Android中只能在主线程中修改UI,耗时操作不能在主线程中执行,所以我们经常会创建新的Thread去执行耗时操作,然后配合Handler修改UI,或者使用AsyncTask。RxJava中使用这两个操作符能够让我们非常方便的处理各种线程问题。

  • SubscribeOn:指定Observable自身在哪个调度器上执行(即在那个线程上运行),如果Observable需要执行耗时操作,一般我们可以让其在新开的一个子线程上运行,好比AsyncTask的doInBackground方法。
    这里写图片描述

  • ObserveOn:可以使用observeOn操作符指定Observable在哪个调度器上发送通知给观察者(调用观察者的onNext,onCompleted,onError方法)。一般我们可以指定在主线程中观察,这样就可以修改UI,相当于AsyncTask的onPreExecute 、onPrograssUpdate和onPostExecute 方法中执行

这里写图片描述

关于RxJava的多线程调度器“Scheduler”,后面会有一篇博客详细介绍。

示例代码:

Observable<Integer> observable = Observable.just(1,2);

        observable.subscribeOn(Schedulers.io())
        .map(new Func1<Integer, Integer>() {

            @Override
            public Integer call(Integer t) {
                System.out.println("map thread : " + Thread.currentThread().getName());
                return t * 10;
            }
        })
        .observeOn(Schedulers.newThread())//对应android是:AndroidSchedulers.mainThread()
        .subscribe(new Action1<Integer>() {

            @Override
            public void call(Integer value) {
                System.out.println("subscribe thread : " + Thread.currentThread().getName());
                System.out.println("onNext: " + value);
            }
        });

输出:

map thread : RxIoScheduler-2
map thread : RxIoScheduler-2
subscribe thread : RxNewThreadScheduler-1
onNext: 10
subscribe thread : RxNewThreadScheduler-1
onNext: 20

TimeInterval

TimeInterval操作符拦截原始Observable发射的数据项,替换为两个连续发射物之间流逝的时间长度。 也就是说这个使用这个操作符后发射的不再是原始数据,而是原始数据发射的时间间隔。新的Observable的第一个发射物表示的是在观察者订阅原始Observable到原始Observable发射它的第一项数据之间流逝的时间长度。 不存在与原始Observable发射最后一项数据和发射onCompleted通知之间时长对应的发射物。timeInterval默认在immediate调度器上执行,你可以通过传参数修改。
这里写图片描述

示例代码:

Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                for (int i = 3; i <= 7; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    subscriber.onNext(i);
                }
                subscriber.onCompleted();
            }
        })
        .subscribeOn(Schedulers.io())
        .timeInterval()
        .subscribe(new Subscriber<TimeInterval<Integer>>() {

            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(TimeInterval<Integer> t) {
                System.out.println("onNext: " + t.getValue() + " - " + t.getIntervalInMilliseconds());
            }
        });

输出:

onNext: 3 - 1002
onNext: 4 - 1006
onNext: 5 - 1003
onNext: 6 - 1005
onNext: 7 - 1003
onCompleted

Timeout

如果原始Observable过了指定的一段时长没有发射任何数据,Timeout操作符会以一个onError通知终止这个Observable,或者继续一个备用的Observable。

这里写图片描述

RxJava中的实现的Timeout操作符有好几个变体:

  • timeout(long,TimeUnit): 第一个变体接受一个时长参数,每当原始Observable发射了一项数据,timeout就启动一个计时器,如果计时器超过了指定指定的时长而原始Observable没有发射另一项数据,timeout就抛出TimeoutException,以一个错误通知终止Observable。 这个timeout默认在computation调度器上执行,你可以通过参数指定其它的调度器。
  • timeout(long,TimeUnit,Observable): 这个版本的timeout在超时时会切换到使用一个你指定的备用的Observable,而不是发错误通知。它也默认在computation调度器上执行。
  • timeout(Func1):这个版本的timeout使用一个函数针对原始Observable的每一项返回一个Observable,如果当这个Observable终止时原始Observable还没有发射另一项数据,就会认为是超时了,timeout就抛出TimeoutException,以一个错误通知终止Observable。
  • timeout(Func1,Observable): 这个版本的timeout同时指定超时时长和备用的Observable。它默认在immediate调度器上执行
  • timeout(Func0,Func1):这个版本的time除了给每一项设置超时,还可以单独给第一项设置一个超时。它默认在immediate调度器上执行。
  • timeout(Func0,Func1,Observable): 同上,但是同时可以指定一个备用的Observable。它默认在immediate调度器上执行。
    示例代码:
Observable<Integer> observable = Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(i*100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    subscriber.onNext(i);
                }
                subscriber.onCompleted();
            }
        });

        observable
        .timeout(200, TimeUnit.MILLISECONDS, Observable.just(100,200))
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("onError: " + e.getMessage());
            }

            @Override
            public void onNext(Integer integer) {
                System.out.println("onNext: " + integer);
            }
        });

输出:

onNext: 0
onNext: 1
onNext: 100
onNext: 200
onCompleted

Timestamp

它将一个发射T类型数据的Observable转换为一个发射类型为Timestamped的数据的Observable,每一项都包含数据的发射时间。也就是把Observable发射的数据重新包装了一下,将数据发射的时间打包一起发射出去,这样观察者不仅能得到数据,还能得到数据的发射时间。 timestamp默认在immediate调度器上执行,但是可以通过参数指定其它的调度器。

这里写图片描述

示例代码:

Observable.just(1,2,3)
        .timestamp()
        .subscribe(new Subscriber<Timestamped<Integer>>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(Timestamped<Integer> t) {
                System.out.println("onNext: " + t.getValue() + " ,time:" + t.getTimestampMillis());
            }
        });

输出:

onNext: 1 ,time:1486018751879
onNext: 2 ,time:1486018751880
onNext: 3 ,time:1486018751880

Using

Using操作符指示Observable创建一个只在它的生命周期内存在的资源,当Observable终止时这个资源会被自动释放。
using操作符接受三个参数:

  • 一个用于 创建一次性资源的工厂函数
  • 一个用于创建Observable的工厂函数
  • 一个用于释放资源的函数

当一个观察者订阅using返回的Observable时,using将会使用Observable工厂函数创建观察者要观察的Observable,同时使用资源工厂函数创建一个你想要创建的资源。当观察者取消订阅这个Observable时,或者当观察者终止时(无论是正常终止还是因错误而终止),using使用第三个函数释放它创建的资源。

这里写图片描述

示例代码:

Observable.from(studentList)
        .using(new Func0<Integer>() {

            @Override
            public Integer call() {
                 return new Random().nextInt(100);
            }
        }, new Func1<Integer, Observable<String>>() {

            @Override
            public Observable<String> call(Integer t) {
                return Observable.just("西部世界接待员-" + t);

            }
        }, new Action1<Integer>() {

            @Override
            public void call(Integer t) {
                t = null;
            }
        }).subscribe(new Action1<String>() {

            @Override
            public void call(String t) {
                System.out.println("call : " + t);
            }
        });

输出:

call : 西部世界接待员-64

To

将Observable转换为另一个对象或数据结构。它们中的一些会阻塞直到Observable终止,然后生成一个等价的对象或数据结构;另一些返回一个发射那个对象或数据结构的Observable。简而言之就是,将原始Observable转化为一个发射另一个对象或者数据结构的Observable,如果原Observable发射完他的数据需要一段时间,使用To操作符得到的Observable将阻塞等待原Observable发射完后再将数据序列打包后发射出去。

这里写图片描述

RxJava中实现了如下几种To操作符:

  • toList:发射多项数据的Observable会为每一项数据调用onNext方法,用toList操作符让Observable将多项数据组合成一个List,然后调用一次onNext方法传递整个列表。
    如果原始Observable没有发射任何数据就调用了onCompleted,toList返回的Observable会在调用onCompleted之前发射一个空列表。如果原始Observable调用了onError,toList返回的Observable会立即调用它的观察者的onError方法。

  • toMap: toMap收集原始Observable发射的所有数据项到一个Map(默认是HashMap)然后发射这个Map。你可以提供一个用于生成Map的Key的函数,还可以提供一个函数转换数据项到Map存储的值(默认数据项本身就是值)。

  • toMultiMap:toMultiMap类似于toMap,不同的是,它生成的这个Map同时还是一个ArrayList(默认是这样,你可以传递一个可选的工厂方法修改这个行为)。

  • toSortedList:toSortedList类似于toList,不同的是,它会对产生的列表排序,默认是自然升序,如果发射的数据项没有实现Comparable接口,会抛出一个异常。然而,你也可以传递一个函数作为用于比较两个数据项,这是toSortedList不会使用Comparable接口。

  • toFuture:toFuture操作符只能用于BlockingObservable(首先必须把原始的Observable转换为一个BlockingObservable。可以使用这两个操作符:BlockingObservable.from或the Observable.toBlocking)。这个操作符将Observable转换为一个返回单个数据项的Future,如果原始Observable发射多个数据项,Future会收到一个IllegalArgumentException;如果原始Observable没有发射任何数据,Future会收到一个NoSuchElementException。
    如果你想将发射多个数据项的Observable转换为Future,可以这样用:myObservable.toList().toBlocking().toFuture()。

  • toIterable:只能用于BlockingObservable。这个操作符将Observable转换为一个Iterable,你可以通过它迭代原始Observable发射的数据集。

示例代码:

Observable.interval(500, TimeUnit.MILLISECONDS).take(3)
        .toList()
        .subscribe(new Subscriber<List<Long>>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(List<Long> longs) {
                System.out.println("onNext : " + longs);
            }
        });

输出:

onNext : [0, 1, 2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值