rxjava从源码完全理解运行原理

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

响应式拉取:

img

onstart -》request()

onNext-》request

rxjava1有些操作不支持背压,是因为interval操作符本身并不支持背压策略,它并不响应request(n),也就是说,它发送事件的速度是不受控制的,而range这类操作符是支持背压的,它发送事件的速度可以被控制。

那么到底什么样的Observable是支持背压的呢?

冷热Observables

我们一般使用的都是Cold Observable,除非特殊需求,才会使用Hot Observable,在这里,Hot Observable这一类是不支持背压的,而是Cold Observable这一类中也有一部分并不支持背压(比如interval,timer等操作符创建的Observable)。

那么,不支持背压的Observevable如何做流速控制呢?

  1. 使用操作符,有些操作函数可以减少发送给消费者的数据。
    • 过滤(抛弃)
      • 相关类似的操作符: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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值