1.创建符
1.1 Observable
创建函数用于创建一个Observable对象,它们都是Observable的静态方法,通过Observable.创建
1.create
Observable.create(emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onComplete();
}
);
2.from
Observable.fromArray(1, 2, 3);
Observable.fromArray(new int[]{1,2,3});
Observable.fromArray(new ArrayList());
Observable.fromIterable(new HashSet<>());
Observable.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return getString(); //通过某个函数获取要发送的值
}
});
Observable.fromFuture(Future<? extends T> future);
4.defer
直到有观察者订阅时,才动态创建被观察者对象
Observable.defer(new Callable<ObservableSource<? extends Integer>>() {
@Override
public ObservableSource<? extends Integer> call() throws Exception {
return Observable.just(i);
}
});
Observable.defer(()->Observable.just(i));
5.timer
延迟指定时间后,发送一个Long类型的数值0
Observable.timer(10, TimeUnit.SECONDS);
6.interval
每个一段时间发送一个从0递增的Long型整数,0,1,2,3…
//每隔10s发送一个整数,初始延迟为10s
Observable.interval(10, TimeUnit.SECONDS)
//每隔10s发送一个整数,初始延迟为5s
Observable.interval(5, 10, TimeUnit.SECONDS)
7.range
Observable.range(10, 5) //发送10,11,12,13,14共5个整数
8.amb
接收多个数据源,但只会发射最先试图发射的数据源,其他的都会被过滤掉,例如:
//在这个例子中,观察者只会观察到1,2,3
Observable.ambArray(Observable.just(1, 2, 3), Observable.just(4, 5, 6), Observable.just(7, 8, 9))
//在这个例子中,观察者只会观察到4, 5, 6
Observable.ambArray(Observable.just(1, 2, 3).delay(1, TimeUnit.SECONDS), Observable.just(4, 5, 6))
1.2 发射单个数据
Observable可以同来发射一连串的事件,而Single
,Completable
和Maybe
用来创建只能发射一个数据或事件的被观察者
它们的创建方法和Observable非常相似,都是调用自身的静态方法,这里主要记录三者的区别:
首先观察者可能会观察到这样一些事件:
onSuccess(Object o) //观察者通过这个回调接收一个数据,在Observable类的观察者类中这个方法叫做onNext
onComplete() //用来观察事件完成发射的事件,没有参数所以并不能传递数据
onError(Throwable e) //用来观察事件
Single类只能发射单个数据,或者单个错误,不能发射完成事件
public interface SingleObserver<T>{
onSubscribe(Disposable d);
onSuccess(T t);
onError(Throwable e);
}
Completable类能发射单个完成事件,或单个错误,不能发射数据
public interface CompletableObserver<T>{
onSubscribe(Disposable d);
onComplete();
onError(Throwable e);
}
Maybe类能发射单个数据,或者单个错误,或单个完成事件
public interface MaybeObserver<T>{
onSubscribe(Disposable d);
onSuccess(T t);
onComplete();
onError(Throwable e);
}
需要注意的是,这些类只能发射一个事件,以Maybe为例,它不能发射一个数据和一个完成事件,只能发射一个数据或一个完成事件,例如:
Maybe.create(emitter -> {
emitter.onComplete();
emitter.onSuccess("s");
emitter.onError(new NullPointerException());
})
上面的的例子中,观察者只会观察到完成事件,数据会被忽略,错误事件也无法被观察者接住,导致程序崩溃,发射的东西必须是三选一;Single和Completable也是同理。
1.3 Flowable背压:
背压是指数上游据源发送数据速率过快,而下游观察者处理数据过慢,导致数据积压在缓存中,最终导致内存溢出
Rxjava提供了新的数据发射器Flowable
和新的观察者Subscriber
解决背压问题
Flowable.create(emitter -> emitter.onNext(0), BackpressureStrategy.ERROR) //1.create方法中多了背压策略
.subscribe(new Subscriber<Object>() {
@Override
public void onSubscribe(Subscription s){ //2.onSubscribe参数变成了Subscription
s.request(3); //3.设置下游只接收3条消息,多余的还是会存在缓存
s.request(4) //如果调用两次request,下游将会接收3+4=7条消息
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
}
背压策略:
public enum BackpressureStrategy {
MISSING, //相当于没有指定背压策略
ERROR, //Flowable缓存池(大小128)溢出会抛出一个MissingBackpressureException
BUFFER, //缓存无穷大
DROP, //如果Flowable缓存池满了,会丢掉数据源新发送的消息
LATEST
}
数据上游获取消息缓存数量:
FlowableEmitter相比ObservableEmitter多了requested这个方法:
public interface FlowableEmitter<T> extends Emitter<T> {
void setDisposable(Disposable s);
void setCancellable(Cancellable c);
long requested();
boolean isCancelled();
FlowableEmitter<T> serialize();
}
Flowable发送数据并是直接发送给下游,而是发送给缓存,缓存再把数据转发给下游
requested方法可以获取缓存池还能放几条消息,当request方法返回0时,说明缓存池已经满了,上游应当暂停发射消息;
通过Flowable得到一个背压的解决方案:
Flowable.create(emitter -> {
while (true) {
if (emitter.requested() == 0) continue; //缓存装满,暂停发送数据
emitter.onNext(0);
}
}
, BackpressureStrategy.MISSING)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Subscriber<Integer>() {
Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
s.request(1);
subscription = s;
}
@Override
public void onNext(Integer n) {
handle(n); //模拟一个耗时操作
subscription.request(1); //处理完消息再允许缓存释放一个消息
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
}
);
1.4 Subject:
2.操作符
操作符都是Observable的非静态方法,在创建Observable对象之后对它进行一些变换操作
2.1 过滤操作符:
防抖
可以通过防抖避免频繁触发某事件,如果在试图发射事件之后的n秒后没有再次发射事件,那么这个事件才会通过debounce过滤,真正发射出来,例如:
Observable.create(emitter -> {
emitter.onNext(0); //t = 0
Thread.sleep(1000);
emitter.onNext(1); //t = 1000时,距离上一个时间触发只有1000ms,所以0不会被观察到
//t = 3000时,距离上一个时间触发达到2000ms,所以1会被观察到
}).debounce(2, TimeUnit.SECONDS)
所以debounce是自带延时
的,如果防抖时间为n秒,那么观察者看到事件的时刻总是比实际发射时刻晚n秒
其他
//take和skip,是相反的操作符
Observable.just(1, 2, 3, 4, 5).take(3) //订阅者只能接收到1,2,3
take(n, TimeUnit.SECONDS) //订阅者只能接收到前n秒发送的消息
Observable.just(1, 2, 3, 4, 5).takeLast(3) //订阅者只能接收到3,4,5
takeLast(n, TimeUnit.SECONDS) //订阅者只能接收到最后n秒发送的消息
Observable.just(1,2,3,4,3,4,5).distinct() //1,2,3,4,5
Observable.just(1,3,3,4,3,4,5).distinctUntilChanged() //1,3,4,3,4,5
Observable.just(1,2,"3").ofType(Integer.class) //过滤出某种类型的数据
Observable.just(1, 2, 3).filter(i -> i > 2) //自定义过滤条件
条件操作符:
通过条件操作符可以使得不符合条件的数据源产生错误
1.single
single保证了数据源只能发送一个数据,它的参数指定了没有数据发送时的默认发送值
Observable.just(1).single(1) //发射1
Observable.just(1,2).single(1) //报错
Observable.empty().single(2) //发射2
2.all
判断是否每个数据都满足某个条件,通过all的多个数据会被转化为一个boolean值
Observable.just(1, 2, 3).all(i -> i < 4) //发射true
Observable.just(1, 2, 3).all(i -> i < 3) //发射false
3.contain
判断是否每个数据都满足某个条件,通过all的多个数据会被转化为一个boolean值
Observable.just(1, 2, 3).contains(3) //发射true
变换操作符:
1.map,flatMap
以下两种写法是相同的效果,flatMap完全可以实现map的所有功能
Observable.just(1,2,3).map(n->2*n)
Observable.just(1,2,3).flatMap(n->Observable.just(2*n))
flatMap接收一个Function做为参数,它的作用就是把T类型的参数变成R类型的参数:
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)
public interface Function<T, R> {
R apply(@NonNull T t) throws Exception;
}
可以看到flatMap使用被发射的数据重新创建了一个数据源,一个数据源又可以包含多个数据,可以使用flatMap方便地完成一对多的映射
2.flatMap和concatMap的区别:
经过flatMap变换后的数据不一定保持原来的顺序,而concatMap变换后数据一定会保持原始顺序,例如:
//如果事件2的发射遇到一些延时,观察者接收到的消息顺序就会变成1,3,2
Observable.just(1,2,3).flatMap(n->Observable.just(n)).subscribe()
//不论发生什么,观察者一定会按1,2,3的顺序接收到数据
Observable.just(1,2,3).concatMap(n->Observable.just(n)).subscribe()
3.cast
作用是把数据源的每一个数据都做类型强制转换,例如:
Observable.just(1,2,3).case(String.class)
4.concatWith和mergeWith
把两个事件序列合并成一个事件序列,区别只是在于数据合并后是否按合并前的顺序被观察者接收到
Observable.just(1,2,3)
.delay(1, TimeUnit.SECONDS)
.concatWith(Observable.just(4,5,6)) //发射1,2,3,4,5,6
Observable.just(1,2,3)
.delay(1, TimeUnit.SECONDS)
.mergeWith(Observable.just(4,5,6)) //发射4,5,6,1,2,3
5.zipWith
把两个事件序列压缩为一个,参数是另外一个事件源,和一个用来说明压缩规则的函数
Observable.just(1, 2, 3, 4).zipWith(Observable.just(4, 5, 6), (a, b) -> a + b); //发射5,7,9
6.reduce
把一个事件序列通过某种算法压缩成Maybe类型发送给观察者
Observable.just(1, 2, 3, 4).reduce((a, b) -> a + b) //发射10(1+2+3+4=10)
7.compose
compose操作符的作用是为了避免链式调用时出现过多的模板代码,例如:
repository.login()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
如果不想在每个网络请求下面写同样的代码,可以使用compose将这些代码封装起来,就会好看很多
compose方法的参数是一个Transformer对象,首先定义一个方法返回Transformer对象,Transformer定义如下:
public interface ObservableTransformer<Upstream, Downstream> {
ObservableSource<Downstream> apply(@Observable<Upstream> upstream);
}
可以看到它的唯一方法apply是将一个Observable变换成另一个Observable;
首先写一个返回类型为Transformer的方法,这个Transformer中封装线程切换的操作符:
<T> ObservableTransformer<T, T> applySchedulers() {
return observable -> observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
然后就可以使用compose操作符:
repository.login().compose(applySchedulers())
2.5 其他操作符:
retry和repeat
数据源发射error时会触发retry,发射complete时会触发repeat;
retry(n)在数据源发射error后使数据再重发至多n次,repeat(n)在数据源发射complete后再使数据重发至多n次;
retry()会一直重试直到没有error发射,repeat()会一直重复直到有error发射
retry(Predicate)可以自定义某些error不触发重试
retryWhen
retryWhen接收一个Function作为参数:
public final Observable<T> retryWhen(Function<Observable<Throwable>, ObservableSource<?>> handler)
public interface Function<T, R> {
R apply(T t) throws Exception;
}
Function的作用是将Observable<Throwable>转化为另一个Observable,这个Observable的类型决定了是否会重新触发事件源发射事件,例如:
Observable.create(emitter -> {
emitter.onNext(1);
emitter.onError(new NullPointerException());
}).retryWhen(throwableObservable -> {
//这里要用flatMap把Observable<throwable>转换为其他消息
throwableObservable.flatMap(throwable ->
//返回Error事件后,观察者会接收到这个错误
Observable.error(new RuntimeException()))
// 返回next事件后,观察者会收到无穷多的1,这里onNext的参数是什么都无所谓,重要的是触发onNext
// Observable.just(0))
}).subscribe(data -> {
print(data);
}, throwable -> {
print(throwable.toString());
});