RxJava线程切换的原理

1.当观察者订阅主题(被观察者)时:

  • 会马上执行ObservableCreate()方法中的subscribeActual()方法
  • 在subscribeActual()方法中创建CreateEmitter()的实例,CreateEmitter()接口实现了Emitter(onNext,onError,onComplete)和Disposeable接口
  • observer 调用onSubscribe方法,获取上游的控制权
  • 接着执行ObserableOnSubscribe()的subscribe()方法,通过传入的CreateEmitter()实例开始执行Emitter中的方法
  • 在CreateEmitter()方法内部,Observer接口中对应的方法依次执行,实现一次从主题到观察者的事件传递

 2.Observable调用subscribeOn(Scheduler scheduler):

  • 实际上是调用了new ObservableSubscribeOn<T>(this, Schedulers.newThread());  this->是指当前的Observable
  • 通过ObservableSubscribeOn()继承HasUpStreamObservableSource<T>可知,它的source()方法返回类型是ObservableSource<T>,代表该Observable拥有关键的source属性,是拥有上游的observable
  • 在ObservableSubscribeOn()的构造函数中调用父类构造函数AbstractObservableWithUpstream的构造函数,创建一个包含上游的ObservableSubscribeOn()实例
  • 在ObservableSubscribeOn()的subscribeActual()方法中,创建subscribeOnObserver()的实例,这个实例同时实现了Observer和Disposable接口,可视作一个Observer
  • 重点在subscribeActual()方法中的最后一句:parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
  • SubscribeTask实现了Runnable接口,在run()方法要执行是实现ObservableSubscribeOn的上游和Observer的订阅的操作。一旦某个线程执行了这个Runnable(SubscribeTask),就会触发了这个run方法,从而实现订阅。
  • 在scheduleDirect()方法中,通过createWorker()方法创建一个Worker对象w,通过传入的SubscribeTask和Worker对象生成一个DisposeTask对象task,通过Worker的schedule方法开始执行这个task

  在subscribeOn()方法的分析已经到了尽头,通过scheduleDirect()方法得出的结论:

  • 最终的Runnable任务,将由某个具体的Worker对象的scheduler()方法执行。
  • 这个scheduleDirect会返回一个Disposable对象,这样我们就可以通过Observer去控制整个上游的执行了。

3.subscribeOn()方法中传入的Scheduler类型参数,是通过Schedulers静态工厂来生成的。在工厂中,不同的方法(io/newThread)会生成不同Scheduler(IoScheduler/NewThreadScheduler)实例并返回

  • 在对应类型的Scheduler中,静态代码块中构造一个普通优先级(priority = 5)的线程工厂
  • createWorker()方法中,利用该线程工厂创建一个NewThreadWorker()的实例
  • 在NewThreadWorker的构造函数中,通过SchedulerPoolFactory.create()方法,传入线程工厂创建一个ScheduledExecutorService
  • SchedulerPoolFactory.create()方法中,通过Executors创建一个核心线程为1的子线程

结合上面分析subscribeOn()方法,整个切换到子线程的过程为:

  1. Observable调用subscribeOn()方法
  2. 在通过Schedulers静态工厂生成需要传入的Scheduler类型时,构建一个普通优先级的线程工厂ThreadFactory,通过Excutors创建一个核心线程为1的子线程对象executor
  3. 当在Observable调用subscribe()方法时,会执行ObservableSubscribeOn()中subscribeActual()方法的parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent))
  4.  SubscribeTask类引用Runnable,将订阅操作source.subscribe()放在run()方法中,完成把任务放到子线程中 
  5. scheduleDirect()方法中,调用createWorker()方法创建一个worker对象,通过worker.schdule()方法将刚创建好的子线程对象executor通过executor.submit()或executor.schedule()执行subscribeTask的run()方法中的订阅操作 

---------------- ---------------------------------------------------------------------------------------------------------

---------------- ---------------------------------------------------------------------------------------------------------

当Observable调用observerOn(AndroidSchedulers.mainThread())时:

1.AndroidSchedulers.mainThread()的实现:

  • 首先HandlerScheduler通过构造函数获取到了主线程所在的 Handler实例(new Handler(Looper.getMainLooper()))
  • HandlerSchedulercreateWorker()方法中,通过这个主线程Handler实例创建了一个HandlerWorker的实例,这个HandlerWorker本质上就是一个Worker。
  • HandlerWorkerschedule()方法中,创建了一个ScheduleRunnable对象,并会把这个Runnable对象通过handler的sendMessageDelayed方法发送出去。这个Handler是主线程,因此在下游中,就把任务从某个子线程转移到了UI线程

2.observerOn()的实现:

  • 调用new ObserverObserveOn(),该方法类也继承了AbstractObservableWithUpstream,这样他也是一个拥有上游的Observeable
  • 在Observable调用subscribe()方法的时候,会执行ObserverOn中的subscribeActual()方法 --> 在该方法中,通过传入的scheduler(即AndroidSchedulers.mainThread())调用CreateWorker()创建一个worker对象
  • 传入worker对象创建ObserveOnObserver()对象,该对象是Observer同时也是Runnable。在执行onNext()/onComplete()会调用worker对象的schedule()方法。将该ObserveOnObserver()中run()方法中的任务放到主线程去处理

3.执行订阅subscribe()方法后,函数响应顺序为:

Observable.subscribe--->Observable.subscribeActual---> ObservableObserveOn.subscribeActual---> ObservableSubscribeOn.subscribeActual--->ObservableCreate.subscribeActual

这些方法的参数均为 observer,通过层层回调,最后的subscribeActual(Observer<? super T> observer)执行时,这个 observer持有之前几个observer的引用。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RxJava 切换线程内存泄漏的原因可能有以下几点: 1. 订阅关系未正确取消:在使用RxJava进行线程切换时,如果没有正确取消订阅关系,就可能导致内存泄漏。因为订阅关系会持有被观察者和观察者之间的引用,如果未及时取消订阅,就会导致观察者无法被释放,从而造成内存泄漏。 2. 使用错误的调度器:在RxJava中,切换线程需要使用Scheduler来指定要切换到的线程。如果使用了错误的调度器,可能导致线程资源无法正确释放,从而造成内存泄漏。 3. 长时间运行的任务:如果在使用RxJava进行线程切换时,执行的任务是一个长时间运行的任务,可能会导致内存泄漏。因为长时间运行的任务可能会持有一些资源,如果没有及时释放这些资源,就会造成内存泄漏。 为避免RxJava切换线程内存泄漏,可以采取以下几个措施: 1. 及时取消订阅关系:在不需要继续观察的时候,及时取消订阅关系,可以使用CompositeDisposable来管理多个订阅关系,确保在不需要时能够正确取消订阅。 2. 使用正确的调度器:在进行线程切换时,确保使用正确的调度器,比如使用Schedulers.io()进行IO操作,使用AndroidSchedulers.mainThread()进行主线程操作。 3. 避免长时间运行的任务:如果任务可能会持续较长时间,可以考虑使用takeUntil等操作符来限制任务的执行时间。 通过以上措施,可以有效避免RxJava切换线程内存泄漏的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值