rxjava1
概念理解
Observable、Observer、subscriber、actionN、funcN、Operator、Producer对元素变换、Transformer对Observable变换。
subscriber继承自Observer观察者父接口,继承Subscription可以实现取消订阅
Downstream
代表转换后的数据流,Upstream
代表转换前的数据流。
OnSubscribe
1、本质是函数对象action1.call(),是观察者的父接口,
2、每个Observable有一个OnSubscribe对象,表示当前操作符,subscribe()时调用OnSubscribe的call方法
3、每种操作符都是一个OnSubscribe对象,命名方式是OnSubscribe*比如OnSubscribeMap类
4、每个OnSubscribe类都引用下一个Subscriber(因为subscribe()之后call是从后往前调用的,将当前传个上一个),和当前的Observable,OnSubscribe.call()新创建一个*Subscriber监听subscribe()当前的observable,
5、*Subscriber.onNext()执行*操作符的逻辑比如map操作调用传入的Func1函数对象的call()
Observable
RxJavaHooks
public abstract class Subscriber<T> implements Observer<T>, Subscription {
Subscription
Producer
事件源,可以被中途替换
ObservableSource
原理
核心实现原理机制在于:订阅后向前触发事件subscribe.call、事件向后传递触发业务回调observe.onnext
Observable是工具类,被观察者,也是个容器类,包含了OnSubscribe和Observer(Subscriber)。
1、每个操作符* 都是创建新的Observable返回给下一个操作符**,最后一个操作符subscribe()后,
2、调用当前Subscriber的OnStart(),调用前一个操作符生成的Observable的OnSubscribe *.call(),OnSubscribe *.call()生成新的 *Subscriber 调用前一个Observable.subcribe(),
3、再次触发前前一个OnSubscribe()的call,依次类推,直到最开始的OnSubscribe.call(),如果到了最开始的call则是调用Producer生产元素。
4、如FromArrayProducer,然后开始调用OnNext,最后调用OnCompeleted()
OnSubscribe *.call()
@Override
public void call(final Subscriber<? super R> o) {
MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
o.add(parent);
source.unsafeSubscribe(parent);
}
FromArrayProducer
void fastPath() {
final Subscriber<? super T> child = this.child;
for (T t : array) {
if (child.isUnsubscribed()) {
return;
}
child.onNext(t);
}
if (child.isUnsubscribed()) {
return;
}
child.onCompleted();
}
每个OnSubscriber的onNext会调用下一个Subscriber的OnNext(),而*(map)Subscriber的OnNext调用业务Func.call函数执行转换操作,同时调用下一个Subscriber的onNext,行成链式调用OnNext()
@Override
public void onNext(T t) {
R result;
try {
result = mapper.call(t);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
unsubscribe();
onError(OnErrorThrowable.addValueAsLastCause(ex, t));
return;
}
actual.onNext(result);
}
最后调用onComplete()
框内的对象都是中间对象,对api使用者不可见,完整的调用流程如下图所示。
自定义操作符
lift和compose
lift
操作符对象是元素
调用原理:参考上一节原理类似,但有区别
lift代码
每个observable都有一个OnSubscribe对象,下一层能拿到这个对象调用他的call(),下一层Observable调用call的参数是将自己的Subscriber传入。
- 原理和一般的操作符类似,创建一个中间Observable,subscribe()时其onSubscribe.call被调用,进而创建新Subscriber,下一步有区别,像map是通过subscribe()来触发上一层的onSubscribe.call,而lift是直接调用上层的onSubscribe.call。
- 还有一点区别是Subscriber是用户传进来的,map()是固定的MapSubscriber所以达到自定义操作符的目的,即是有用户来定义Subscriber的实现
- 所以结论就是,定义操作符就是定义Subscriber的实现,参考各种操作符的实现即可。
// map的向上传递方式
注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public Subscription subscribe(Subscriber subscriber) {
subscriber.onStart();
//调用lift生成的onSubscribe
onSubscribe.call(subscriber);
return subscriber;
}
// lift的向上传递方式
注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
@Override
public void call(Subscriber subscriber) {
//下一个subscriber调用了这个call,这个call调用了operator的call执行转换操作
Subscriber newSubscriber = operator.call(subscriber);
newSubscriber.onStart();
//被下一个subscribe调用call之后调,用上一层onSubscribe的call,将代理newsubscriber传入到上一层,进行上下关联,类似交换机
onSubscribe.call(newSubscriber);
}
});
}
实践
简单实现:
定义操作符就是定义Subscriber的实现,操作各种操作符的实现即可。
有些需要再中间插入Producer改变后端消费的元素。
public static void main(String[] args) {
ArrayList<Object> objects = new ArrayList<>();
objects.add("1");
objects.add("2");
objects.add("3");
objects.removeIf(a -> "1".equals(a));
System.out.println(objects);
Observable.from(objects).lift(new Observable.Operator<String, String>() {
@Override
public Subscriber<? super String> call(Subscriber<? super String> subscriber) {
return new Subscriber<String>() {
@Override
public void onCompleted() {
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
subscriber.onError(e);
}
@Override
public void onNext(String s) {
s = s + "lift";
subscriber.onNext(s);
}
@Override
public void onStart() {
super.onStart();
System.out.println("onstart");
}
};
}
}).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onStart() {
super.onStart();
System.out.println("last onStart");
}
});
}
compose
将多个操作符进行封装,操作对象是observable。
如果我们相对多个流重复利用一系列操作符该怎么办?
事件触发事按照代码顺序执行的。
public static void main(String[] args) {
ArrayList<Object> objects = new ArrayList<>();
objects.add("1");
objects.add("2");
objects.add("3");
objects.removeIf(a -> "1".equals(a));
System.out.println(objects);
Observable.from(objects).cache()
.combineLatest(Arrays.asList(Observable.just("combine")), new FuncN<String>() {
@Override
public String call(Object... args) {
return args.toString();
}
}).map(s->s+"map")
.compose(new Observable.Transformer<String, String>() {
@Override
public Observable<String> call(Observable<String> stringObservable) {
return stringObservable.map(s-> s+"compose");
}
}).subscribe(new Action1<String>() {
@Override
public void call(String o) {
System.out.println(o);
}
});
}
原理
//直接调用transformer的call执行Observable的转换,
public <R> Observable<R> compose(Transformer<? super T, ? extends R> transformer) {
return ((Transformer<T, R>) transformer).call(this);
}
所以实现compose就是将一系列操作符进行封装返回一个新的Observable。
flatmap区别
我们知道,compose和flatMap都是以Observable作为输入,Observable作为输出,那么两者有什么区别呢
1.compose()
是唯一一个能从流中获取原生Observable 的方法,因此,影响整个流的操作符(像subscribeOn()和observeOn())需要使用compose(),
相对的,如果你在flatMap()中使用subscribeOn()/observeOn(),它只影响你创建的flatMap()中的Observable,而不是整个流。
2.当你创建一个Observable流并且内联了一堆操作符以后,compose()会立即执行,flatMap()则是在onNext()被调用以后才会执行,换句话说,flatMap()转换的是每个项目,而compose()转换的是整个流。
背压
一种流控策略,当异步
情况下,上面的 MissingBackpressureException 告诉我们,生产者太快了,我们的操作函数无法处理这种情况。
消费者的补救措施
响应式拉取,通过request()控制生产速度
https://blog.csdn.net/jdsjlzx/article/details/51868640
https://zhuanlan.zhihu.com/p/24473022
响应式拉取:
onstart -》request()
onNext-》request
rxjava1有些操作不支持背压,是因为interval操作符本身并不支持背压策略,它并不响应request(n),也就是说,它发送事件的速度是不受控制的,而range这类操作符是支持背压的,它发送事件的速度可以被控制。
那么到底什么样的Observable是支持背压的呢?
冷热Observables
我们一般使用的都是Cold Observable,除非特殊需求,才会使用Hot Observable,在这里,Hot Observable这一类是不支持背压的,而是Cold Observable这一类中也有一部分并不支持背压(比如interval,timer等操作符创建的Observable)。
那么,不支持背压的Observevable如何做流速控制呢?
- 使用操作符,有些操作函数可以减少发送给消费者的数据。
- 过滤(抛弃)
- 相关类似的操作符:Sample,ThrottleFirst…
- 缓存
- 相关类似的操作符:buffer,window…
- 过滤(抛弃)
-
对于不支持背压的Observable除了使用上述两类生硬的操作符之外,还有更好的选择:onBackpressurebuffer,onBackpressureDrop。
- onBackpressurebuffer:把observable发送出来的事件做缓存,当request方法被调用的时候,给下层流发送一个item(如果给这个缓存区设置了大小,那么超过了这个大小就会抛出异常)。
- onBackpressureDrop:将observable发送的事件抛弃掉,直到subscriber再次调用request(n)方法的时候,就发送给它这之后的n个事件。
但是这两个操作符提供了更多的特性,那就是可以响应下游观察者的request(n)方法了,也就是说,使用了这两种操作符,可以让原本不支持背压的Observable“支持”背压了。
线程调度
1.调用链的拼接是在subscribe()线程执行,包括onstart
2.每个操作符即subscriber默认是在subscribeOn()的线程执行,只能调用这个方法切换一次,第一次有效,作用于整个流的执行
3.每次observeOn()都可以切换subscrier的执行线程,指定特殊的操作符在哪个线程执行,可以切换多次,切换点开始后面的观察者都在这个线程执行,可以覆盖subscribeON的调度
4.observeOn()先于subcribeOn()调用是无效的
public static void main(String[] args) throws InterruptedException {
ArrayList<Object> objects = new ArrayList<>();
objects.add("1");
objects.add("2");
objects.add("3");
objects.removeIf(a -> "1".equals(a));
System.out.println(objects);
Observable.from(objects).cache()
.combineLatest(Arrays.asList(Observable.just("combine")), new FuncN<String>() {
@Override
public String call(Object... args) {
System.out.println("combine+"+Thread.currentThread());
return args.toString();
}
}).subscribeOn(Schedulers.io()).map(s->s+"map")
.compose(new Observable.Transformer<String, String>() {
@Override
public Observable<String> call(Observable<String> stringObservable) {
System.out.println("compose+"+Thread.currentThread());
return stringObservable.map(s-> s+"compose");
}
}).observeOn(Schedulers.newThread()).lift(new Observable.Operator<String, String>() {
@Override
public Subscriber<? super String> call(Subscriber<? super String> subscriber) {
return new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println(Thread.currentThread());
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
System.out.println(Thread.currentThread());
subscriber.onError(e);
}
@Override
public void onNext(String s) {
System.out.println("lift+"+Thread.currentThread());
s = s + "lift";
subscriber.onNext(s);
}
@Override
public void onStart() {
super.onStart();
System.out.println("onstart");
}
};
}
}).observeOn(Schedulers.computation()).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
System.out.println("结果:"+s+Thread.currentThread());
}
@Override
public void onStart() {
super.onStart();
System.out.println("last onStart"+Thread.currentThread());
}
});
Thread.sleep(10000);
}
----结果
[2, 3]
compose+Thread[main,5,main]
last onStartThread[main,5,main]
onstart
combine+Thread[RxIoScheduler-2,5,main]
lift+Thread[RxNewThreadScheduler-1,5,main]
Thread[RxNewThreadScheduler-1,5,main]
结果:[Ljava.lang.Object;@1c5bf81emapcomposeliftThread[RxComputationScheduler-1,5,main]
rxjava2
升级变化
1.api
https://www.jianshu.com/p/d53463e1c3d6
2.实现
1.没有onStart换成了onSubscribe,基本调用流程和原理没有变化,api和名词换了,需要做映射。
2.实现代码更直观
回压
https://www.jianshu.com/p/ceb48ed8719d