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]