Rxjava学习

前些日子在项目中引入了RXJAVA,也算是初步入门了RXJAVA的使用。使用起来感觉还是挺方便的,唯一需要注意的就是线程的切换以及调用的方法是否是在该线程应该使用的。如UI相关操作一定要在主线程中。

一、什么是RXJAVA

RXJAVA是一个库,用来支持我们需求里需要异步操作的地方。它比起handler等异步操作的实现方式来说,显得更为简洁。把整个操作整合成一条流水线,从上游到下游都能够看的清。

二、RXJAVA的原理

RXJAVA的实现,是一种扩展式的观察者模式。

RXJAVA中有四种概念。observable(被观察者),observer(观察者),subscribe(订阅),事件。Observable和Observer通过subscribe来实现订阅关系。与传统的观察者模式不同,除了onNext事件外,rxjava还提供了onCompleted和onError。当不再有onNext事件发送时,将以onCompleted事件作为结束。当处理过程中出现异常时,会触发onError,同时队列自动终止,不允许再有事件发出。onCompleted和onError在一个序列中有且只有一个,二者互斥,只能出现一个。

说了这么多,还是要看源码,看一看源码中,到底是如何实现的。由于本人的项目中使用的是rxjava2,所以源码就按照rxjava2来解析了。

作为事件的发送方,我们需要一个被观察者来发送事件,被观察者是Observale类,使用它的create方法来创建一个实例。在create方法中,只有一个参数,ObservableOnSubscribe<T> ,可以看到这个参数接收泛型,实际上这个T就是我们发送事件时候所要传递的内容。

跟进之后发现ObservableOnSubscribe是一个接口,里面只有一个需要实现的方法,就是subscribe方法,这个方法也是只有一个参数,ObservableEmitter<T>,继续跟进,看到Observable继承自Emitter<T>,增加了setDisposable等方法,而最后来到Emitter,看到它里面有我们熟悉的onNext,onCompleted以及onError方法。

在结合一个创建的常规操作。

至此,我想大家应该都能看明白了。在create方法调用时,我们需要定义subscribe方法被调用时应该做些什么。而这些内容又是由emitter来实现的,如发送哪些事件。而这个subscribe方法看名字大概猜得出是在订阅时被触发。让我们往后看是不是这样。

被观察者Observable还有一个方法,是subscribe。这个方法只接收一个参数,Observer<? super T>,不过这个方法里面相对复杂,我们一步一步看。

首先,先检验传入的观察者是否为空,为空则报错。之后用try尝试对observer进行转换。我们知道rxjava中有一些操作符,就是对observer进行转换操作的,这里调用了RxJavaPlugins里的onSubscribe方法获取到一个转换后的observer。之后又对这个转换后的observer进行了为空校验。最后subscribeActual方法,传入参数是这个转换后的observer。但是跟进后发现subscribeActual是一个抽象方法,那么我们就得去寻找一个它是在哪里实现的。

找了半天,发现刚才只分析了create的参数,但是没有分析其方法。所以还得回到create方法里。

我们看到create方法最后一步return,返回了一个RxJavaPlugins里的onAssembly方法,里面的参数是一个ObserverableCreate方法。看名字应该能猜到这是实例化Observable的地方了。让我们追进去看看。

onAssemble方法会把传入的参数进行func处理,之后还是返回传入的参数,也就是最终获取的就是ObservableCreate方法生成的内容。

跟进ObservableCreate方法后感觉一切就明朗了。先放一张图。

有木有!刚才我们所希望找到的subscribeActual终于出现了。这个ObservableCteate继承自Observable,并且实现了它的抽象方法subscribeActual。让我们捋一捋逻辑。Observerable调用了create方法最终调用了ObservableCreate方法来获取一个实例,这个实例实现了抽象方法subscribeActual,在这个实例调用subscribe方法时,会调用subscribeActual方法。也就是订阅的那一刻,开始发送事件了。

发送事件的内容,就在我们创建的ObservableOnSubscribe的subscribe方法里。现在还剩下一点,发送的事件,是如何做到接收的。这就要看看subscribeActual里的前两行代码了。

先看看CreateEmitter。

CreateEmitter继承自ObservableEmitter,并且构造方法接收一个参数,观察者observer。之后把这个观察者自己持有。之后在自己的onNext方法里调用观察者的onNext。看到这是不是差不多都明白了。emitter调用onNext事件时,会调用其内部持有的观察者的onNext事件。也就完成了上游发送事件,下游接收并处理事件的任务。接下来还有一点,就是observer的onSubscribe方法,看看这里是干什么的。

跟进代码,我们看到onSubscribe方法传进来一个参数Disposable,这个东西实际上是用于拦截的。我们看到CreateEmitter实现了Disposable,并且observer的onSubscribe的方法传进去的就是一个CreateEmitter。而Disposable需要实现两个方法。一个是dispose。一个是isDisposed。这两个方法一个是注册拦截,一个是获取拦截状态。

可以看到这两个方法底层都调用了DisposableHelper类,这是一个查看拦截状态的帮助类。当调用dispose时,就会把这个CreateEmitter注册进去,之后看到调用CreateEmitter的onNext等方法时都会调用isDisposed方法来判断这个发射器是否已经被注册拦截状态了,如果已经被注册,则不再执行后续操作。

好了,到这里,一套发送事件接收事件的流程就梳理完了。让我们简单总结一下每个部分的功能。

被观察者的创建,Observerable调用create方法,传入参数是发送事件的内容。create方法最终调用ObservableCreate方法获取一个实例,实际上是调用了ObservableCteate的构造方法。而ObservableCteate实现了Observable里的抽象方法subscribeActual,这个方法是在Observable的subscribe方法执行时调用,也就是订阅时调用。在subscribeActual方法里,调用CreateEmitter方法生成一个发射器,这个发射器以观察者作为参数,实现了Dispoasble接口和ObservableEmitter接口。CreateEmitter持有观察者,并在自己的onNext等事件里调用观察者的onNext等事件,从而实现发送接收处理。在调用观察者的onNext等事件前,会先判断拦截状态。如果拦截则不做任何操作。我们可以在观察者的onSubscribe方法里获取到发射器(发射器本身实现了拦截接口Disposable),可以持有它,并在后续onNext等事件里决定是否开启拦截,以阻止后续操作。

三、RXJAVA如何实现轻松切换线程的

我们使用RXJAVA的一个比较重要的原因就是它切换线程及其方便。那么还是从源码里看一看,RXJAVA中的切换线程操作是如何实现的。切换线程这部分其实要讲的还挺多的,源码部分内容也不少,后期写一篇专门的文章来总结。本篇主要是总结自己项目中的使用方式。

四、自己如何使用RXJAVA的(网络请求封装)

终于来到重点了。在理解了RXJAVA轻松切换线程的情况下,我们可以在上面大做文章了。网络请求的处理是我们开发过程中需要切换线程比较频繁的地方。通常耗时操作网络请求都会放在子线程中处理,而根据返回结果对UI进行的操作要放在主线程中进行。原始的方法就是在主线程中开启一个子线程,发起网络请求。之后在网络请求回调函数中在post到主线程。也有借助handler来实现的。通常这些方式实现之后,在读代码找关系逻辑的时候真的很绕,需要跳来跳去的。但是有了RXJAVA之后一切就不一样了,把请求和响应全在一条线上搞定。

首先还是来回顾一下RXJAVA的工作流程。Observable创建,添加发送事件内容,选择上游线程,选择下游线程,以Observer为参数订阅,Observer决定响应处理。

在这个流程中,其实我们大部分的操作已经可以实现了,选择上游线程就是新建一个子线程,选择下游线程就是回归到主线程,Observer的响应事件就是在主线程对UI操作的事件。现在唯一的问题就是上游事件如何发送以及发送的时机。

其实在这里最关键的封装就是把网络请求的回调方法放到上游事件发送里,把请求的响应结果作为信号发送,让下游处理。(如果处理的内容比较多,操作复杂,可以处理完再发送。我们的原则是在UI线程里做较少的操作。)那么这一步是如何实现的呢。

建造一个请求帮助类。这个帮助类提供一个发送请求方法,这个发送请求方法接收一个参数,这个参数是网络请求响应的监听接口。在上游调用请求方法,同时new一个监听接口作为参数传递给请求方法。这个监听接口实现的方法,其内容可以调用上游的发射器,将想要发送的内容在上游发送出去。

简单点说,就是让网络请求接口的响应函数,在上游发送事件。这个操作是在上游子线程完成的。

经过这样的封装,我们就实现了异步网络请求结果通知主线程操作。

后续的处理都和平常一样了,值得注意的是由于现在都放在一串代码中执行了,所以很容易忽略两边的操作是处在不同线程的。建议在命名方法时,标注出此方法是在哪种线程中使用的,这样代码的逻辑更加清晰。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值