Rxjava原理分析

1,573 阅读6分钟

Rxjava概要

  • 当程序进行耗时操作的时候,往往会开启一子线程,通过接口回调来处理结果。但是在实际开发中逻辑业务往往都是很复杂的,所以会形成回调中套回调的地步,因此Rxjava就此而诞生。Rxjava本质上是一个异步操作库。

设计模式

观察者模式

  • 对象间存在一对多关系,当一个对象被修改时,则通知依赖它的对象,被观察者决定什么时候去触发事件
  • 使用场景
    • 一个对象依赖另一个变化而变化
    • 更改一个对象时,同时需要连带改变其它对象
    • 希望通知对象与被通知对象松散耦合时

Rxjava的观察者模式

  • 被观察者
  • 观察者
  • 订阅
  • 事件(响应式编程)

Rxjava使用

  1. 创建被观察者
    • 方式一:create方法
    var observable = Observable.create(object :ObservableOnSubscribe<String>{
            override fun subscribe(emitter: ObservableEmitter<String>?) {
               emitter?.onNext("H")
               emitter?.onNext("I")
               emitter?.onComplete()
        }
    })
    
    • 方式二:just方法
    var observableJust = Observable.just("H","I")
    
    • 方式三:from方法
    val parameters = arrayOf("H","I")
    var observableFromArray = Observable.fromArray(parameters)
    
  • 表示事件顺序发出
  1. 创建观察者
     var observer = object :Observer<String>{
             override fun onSubscribe(d: Disposable?) {
    
             }
    
             override fun onNext(t: String?) {
    
             }
    
             override fun onError(e: Throwable?) {
    
             }
    
             override fun onComplete() {
    
             }
    
    }
    
  • onNext方法对应传统观察者模式中的update方法
  • onComplete在没有新的事件通过被观察者发出时执行
  • onError框架异常时触发
  • onSubscribe提供观察者与被观察者取消连接通道
  1. 订阅
    observable.subscribe(observer)
    
  • 通过被observable观察者调用subscribe方法订阅observer观察者
  • 按正常来说应该是观察者订阅被观察者,而Rxjava这样设计是为了便于后面的链式调用

Rxjava源码分析

被观察者Observable的创建

  • ObservableOnSubscribe是一个接口,在观察者创建时被实例化。里面的subscribe方法提供给订阅调用,方法中emitter发射器永不为空

微信截图_20210804171747.png

  • 实例化后的ObservableOnSubscribe被传入create方法后首先进行判空操作,然后主要的是传入创建new ObservableCreate<>(source)对象
    • 最后在外面实例化后的ObservableOnSubscribe被赋值给ObservableCreate中的source,在观察者模式中被观察用于通知的方法
    • RxJavaPlugins.onAssembly理解为代理类就行

微信截图_20210804180507.png

微信截图_20210804172525.png

观察者创建以及订阅

  • observable.subscribe(observer)方法源码中,可以看到核心的代码是subscribeActual 微信截图_20210804211648.png

  • 由创建被观察者的过程得知subscribeActual的实现方法是ObservableCreate对象中的subscribeActual方法

  • 主要的流程是创建了CreateEmitter对象以及执行类观察者中的onSubscribe回调,以及被观察者的subscribe回调方法

微信截图_20210804221200.png

  • CreateEmitter对象中用onNextonErrortryOnErroronComplete这四个方法,同时可以看出这些方法主要执行观察者observer中的回调,因此这就与观察者observer链接起来了,这个CreateEmitter对象在执行订阅后回调给被观察者Observable,当观察者业务执行emitter?.onNext("H")emitter?.onComplete()时,实现了通知观察者的功能

微信截图_20210804230928.png 微信截图_20210804230949.png

小结

  • 每到我们调用observable.subscribe(observer)订阅时,从源码中都会执行source.subscribe(parent),从而我们的被观察者中的subscribe方法就会被回调,从回调接口中得到ObservableEmitter对象进行下一步的onNextonComplete操作,这样就完成了一次订阅。

操作符

  • Rxjava支持变换
    • 变换:将事件序列中的对象或整个序列进行加工处理转换成新额序列

map

  • 把一个事件转换为另一个事件

map用法

        Observable.just("local/image/map.png")
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String filePath) throws Throwable {
                        return getBitmap(filePath);
                    }
                }).subscribe(new Observer<Bitmap>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull Bitmap bitmap) {
                showBitmap(bitmap);
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

map源码

  • 在源码中可以看出,使用map方法时主要创建ObservableMap对象

微信截图_20210805114949.png

  • ObservableMap源码中看出,它的设计模式与之前分析过的被观察者ObservableCreate是大体一样的,把实例化后funtion在这个类中进行赋值
  • Function接口中有一apply方法,表示接收参数类型为T的参数,返回类型为R的参数,通过Function<? super T, ? extends U>也可以理解为T是输入,U是输出

微信截图_20210805154532.png

  • subscribe订阅时,就会调用subscribeActual方法
  • 注意的是source.subscribe方法的调用,表示我们通过just创建的被观察者订阅一个新的观察者,也就是ObservableJust对象执行了subscribeActual方法

微信截图_20210805115846.png

  • ObservableJust对象执行subscribeActual方法中的run()包含了observer.onNext(value)等方法,因此就证明了Rxjava通过map()方法链式调用的过程 微信截图_20210805171557.png

微信截图_20210805172028.png

flatMap

  • 将传入对象转换成Observable对象
  • 不直接发送转换后的Observable对象,而将它激活让它自己开始发送事件
  • 每一个创建出来的Observable发送的事件都被汇入同一个Observable
  • 与map设计思路大体一致,主要也是订阅时候执行subscribeActual完成业务

flatMap使用

  • 上面分析map场景时,是将String类型转换成Bitmap类型,而flatMap是将String类型转换成Observable类型
        Observable.just("http://www.baidu.com",
                "http://www.sina.com",
                "http://www.sohu.com")
                .flatMap(new Function<String, Observable<String>>() {

                    @Override
                    public Observable<String> apply(String s) throws Throwable {
                        return createObservable(s);
                    }
                }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull String s) {

            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

Rxjava线程控制

  • 在实际网络请求中往往会有很多耗时操作,这就需要在子线程完成再把结果返回到主线程,从而就涉及到了线程的切换
  • Rxjava是线程不变原则,哪个线程产生就在哪个线程消费
  • Rxjava通过Schedulers类进行线程调度

Schedulers中线程控制符

  • Schedulers.newThread()启动新线程,在新线程操作
  • Schedulers.io()执行I/O操作,与newThread()区别在于可以使用无上限线程池,可重用多数控件的线程,效率相对较高
  • Schedulers.computation()用于计算使用Schedulers数
  • AndroidSchedulers.mainThread()切换到主线程也就是UI线程,需要额外导入RxAndroid

Rxjava线程控制方法

  • subscribeOn()指定观察者指定订阅时观察者所发生的线程,也就是Observer内部onSubscribe激活时所处线程
  • observeOn()事件消费线程

使用分析

  Observable.just("H", "E", "L")
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<String>() {
      @Override
      public void onSubscribe(@NonNull Disposable d) {

      } 

      @Override
      public void onNext(@NonNull String s) {

      }

      @Override
      public void onError(@NonNull Throwable e) {

      }

      @Override
      public void onComplete() {

      }
   });
  • 表示在I/O线程中发送"H", "E", "L"三个事件,在主线程中消费
  • observeOn可以多次调用,但subscribeOn只能调用一次,它在observeOn前后都可以
    • 原因是subscribeOn通过Observable链式调用方式所以只会生效第一个,而observeOn通过操作符

subscribeOn源码

  • subscribeOn返回一个Observable被观察者对象,主要的也是创建一个ObservableSubscribeOn对象 微信截图_20210805231909.png
  • 主要是subscribeActual方法,把观察者包装成SubscribeOnObserver对象,然后通知观察者 微信截图_20210805233734.png
  • 接下来主要分析parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)))
    • SubscribeTask是一个任务类,在run方法中执行source.subscribe(parent)的订阅,source就是在ObservableSubscribeOn构造方法中传进来的ObservableCreate对象

微信截图_20210806120048.png - scheduler.scheduleDirect方法中有一重要的成员——WorkercreateWorker()的实现方式在IoScheduler中 - 通过pool.get()从缓存工作者池CachedWorkerPool中获取ThreadWorker

微信截图_20210806145555.png

微信截图_20210806120346.png

微信截图_20210806120412.png

  • SchedulerscheduleDirect方法执行w.schedule(task, delay, unit)时执行IoScheduler类中schedule方法,其中主要的是调用了scheduleActual方法

微信截图_20210806150816.png

  • 创建ScheduledRunnable对象把Runnableparent包装起来,parent是一个DisposableContainer对象,保存所有事件是否被切断状态的容器。最后判断是否设置延迟时间,立即执行调用submit()方法,延迟执行调用schedule()方法

微信截图_20210806151005.png

observeOn源码

  • 在调用observeOn()方法后通过层层包装后最后会创建ObservableObserveOn对象
  • 首先判断调度器是不是TrampolineScheduler(不进行线程切换立即执行当前代码的调度器)
  • 判断成立立即执行source.subscribe(observer)
  • 判断不成立创建Worker并传入ObserveOnObserver对象

微信截图_20210806154917.png

  • ObservableObserveOn中的onNext()onError()onComplete()方法都调用了schedule()
  • schedule()方法中使用了worker.schedule(this)进行了调度实现ObservableObserveOn方法中的Runnable接口,
  • 这里的worker是在AndroidSchedulers.mainThread()中创建,内部原理就是Handler的线程切换,所以这也是为什么observeOn()方法可以多次调用的原因

微信截图_20210806155712.png

微信截图_20210806160245.png

  • 在当前ObserveOnObserverrun()方法中若事件没被融化掉,会执行drainNormal()方法,其中会执行a.onNext()方法,这样就呼应了整个Rxjava链式调用的流程。