• rxjave 面试准备



    首先对rxjave简单的一个认知

    描述:响应式编程,观察者设计模式,实现异步操作的库.

    这个描述并不是很详细但是足够精简,接下来基于描述来分析Rxjava源码中是如何体现了这些特点。(主要为面试自我总结方便记忆)

    代码1:

    Observable
    .create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> e) throws Exception {
    e.onNext("1");
    }
    })
    .map(new Function<String, Integer>() {
    @Override
    public Integer apply(String s) throws Exception {
    return Integer.parseInt(s);
    }
    })
    .subscribe(new Observer<Integer>() {
    @Override
    public void onSubscribe(Disposable d) {
    }
    @Override
    public void onNext(Integer value) {
    }
    @Override
    public void onError(Throwable e) {
    }
    @Override
    public void onComplete() {
    }
    });

    代码1是Rxjava最简单的一个使用,这样能方便我们分析。对代码进行简单分析:

    Rxjava是一个观察者设计模式,那肯定离不开这个模式的套路,(主体成员 1.Observable 被观察者   2.Observer 观察者),

    我们从代码的结构来看,1.通过Observable.create方法创建了一个被观察者,2.subscribe传入了一个观察者,这时候我们找到了两个主体。

     

    订阅流程:

    代码1中Observable在调用create方法后接着调用了map,看下map方法的实现。

    public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
    ObjectHelper.requireNonNull(mapper, "mapper is null");
    return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

    很简单对传入的方法和this进行了一个封装,抛开其他细节,注意最后我们拿到了ObservableMap的对象。可以再去看下其他的一些操作符,发现大致如此这样先得出一个简单结论,

    Observable在各个操作符下进行了一个分装,不同操作符分装成不同的Observablexxx的对象进行返回。

    接着简单看下ObservableMap里面长什么样,

    public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
    super(source);
    this.function = function;
    }

    @Override
    public void subscribeActual(Observer<? super U> t) {
    source.subscribe(new MapObserver<T, U>(t, function));
    }
    ....}

    代码很简单,把传入的this(指Observable,因为是被观察者调用的map方法)取名source存下,把对应的function也保存下来,对照的看一下其他的操作符对应Observablexxx里面的实现就能发现也是大同小异的,这边结合之前再做一个简单的结论:

    Observable在各个操作符下进行了一个分装,不同操作符分装成不同的Observablexxx的对象进行返回。Observablexxx中将持有了上一层级的对象,以及自身的处理操作。

    这边其实就能明白了,Observable 被观察者 调用了多少个操作符就会在外面包装多少层类,最后调用了最外面那层Observablexxx的subscribe方法,传入了Observer观察者。

    public final void subscribe(Observer<? super T> observer) {
    ObjectHelper.requireNonNull(observer, "observer is null");
    try {
    observer = RxJavaPlugins.onSubscribe(this, observer);
    ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
    subscribeActual(observer);
    } catch (NullPointerException e) { // NOPMD
    throw e;
    } catch (Throwable e) {
    ....
    }
    }

    操作主要点1.传入了一个Observer观察者,2.调用了subscribeActual,如同名字意思实际的订阅发生了。
    而在subscribeActual里的操作就上调用上一级的subscribe,但是这边传入的Observer是进行分装过的,传入是Observablexxx对应的
    xxxObserver,这个观察者分装了下一级的观察者以及自身特有的操作,把这个新的观察者通过subscribe返回给了Observablexxx的上一级
    的Observable,无限的套娃到最初的observable的subscribe里。
    可以看到虽然有很多不同的的Observablexxx,但是对应的subscribe操作其实类似就是,而subscribeActual里的操作也都大同小异,
    就是调用上一级的subscribe的,传入自己分装好的observer。
    所以可以看到ObservableOnSubscribe里的收到ObservableEmitter其实就是rxjav基于我们传入的observer层层分装后的观察者。
    触发流程:
    在我们调用onNext就开始触发通知观察者发生了事件,这里调用的是订阅流程中层层分装后的observer,在ObservableEmitter里的
    onNext可以看到代码很简单,主要就是调用了下一级的观察者的onNext,我们再看下MapObserver里也是如此,调用了下一级observer的onNext,
    而主要区别在于传入的参数是map操作符传入的方法调用结果,再去看其他的操作符也都是类似的,做了一些各自操作符对应的处理后把结果传递下取。
    最后传递到我们设置的Observer中的onNext方法里,拿到了我们想要的数据。
    总结:在订阅的流程中把我们的观察者做了层层分装,交给到被观察者,然后被观察者把通知的信息给了分装后的观察者,而这个分装后的观察者
    把通知信息处理了一下,做成了符合下一个观察者想要的东西传递了过去,这样形成了类似工程流水线的模式,把针对通知信息不同的操作进行了划分分装,
    最后在末端我们拿到了想要的东西。这样一来后期添加操作或者去掉操作十分方便,流水线的模式把操作之间完全解耦,
    操作之间互不关联,你只要给下一个操作想要的东西就不会出错。

    线程切换:
    实现线程切换常用的就是subscribeOn和observeOn,对于这两操作符的简单理解:
    subscribeOn:切换操作符上面的线程 observeOn:切换操作符后面的线程
    从结果来看这是没有错的,但是在交错使用比较复杂的情况下的时候,就会很闷逼不确定。
    subscribeOn起效果是发生在订阅流程,根据之前的分析,订阅流程主要操作就是对Observer进行了分装然后调用上一层级Observable的subscribe。
    抱着这个目的我们去看,其实发现里面逻辑就很简单了,在ObservableSubscribeOn里的subscribeActual方法里,对下一层传来的Observer进行里分装成
    SubscribeOnObserver,这个操作很熟悉,然后接下按分析应该就是调用上一级的subscribe,但是这里没有而是再进行了一层封装成了SubscribeTask,
    点开一看就能很熟悉的source.subscribe了,SubscribeTask继承自Runnable,而他的run方法里调用的就是source.subscribe。
    scheduler.scheduleDirect这个方法就是把Runnable放入rxjave中对应的线程池进行运行,这样就切换了后续操作的线程环境。
    observeOn起效果是发生在触发流程里,根据之前分析,触发流程主要操作是实现自身Observer的操作,并调用下一个Observer的onNext方法传递过去。
    在ObservableObserveOn中分装这个ObserveOnObserver时候会把我们设置的线程Scheduler传入,并且ObserveOnObserver是继承Runnable,
    在onNext方法里可以看到,其实就是用我们设置的线程去执行了this,然后可以在ObserveOnObserver中的run方法了看到了很熟悉的onNext方法。
    这样后续的Observer操作都会切换到新的线程里了。

    备注:切换线程具体实现:subscribeOn是线程池 observeOn是handle

  • 相关阅读:
    mina:IoBuffer 常用方法(转载)
    js:对象之间的复制
    jquery与angular的交互
    javax.crypto.BadPaddingException: Given final block not properly padded
    jstree:重新加载数据集,刷新树
    TCP 握手 -> 微服务
    eclipse 中添加source
    02 IO
    为什么常用 Map<> map = new HashMap()
    自组织 Self-Orginaztion
  • 原文地址:https://www.cnblogs.com/fuccc/p/15004367.html
Copyright © 2020-2023  润新知