RxJava响应式编程pdf/doc/txt格式电子书下载
本站仅展示书籍部分内容
如有任何咨询
请加微信10090337咨询
书名:RxJava响应式编程pdf/doc/txt格式电子书下载
推荐语:
作者:李衍顺著
出版社:电子工业出版社
出版时间:2018-04-01
书籍编号:30458600
ISBN:9787121336409
正文语种:中文
字数:102038
版次:1
所属分类:计算机-程序设计
版权信息
书名:RxJava响应式编程
作者:李衍顺
出版社:电子工业出版社
出版日期:2018-04-01
ISBN:9787121336409
版权所有 · 侵权必究
前言
毫无疑问,RxJava是一个非常优秀的开源库,清晰的流式操作和便捷的线程切换为Java和Android开发者提供了有力的帮助。网上有大量介绍RxJava的文章,开发者可以很容易地查找到相关的学习资料。但是由于RxJava入门比较困难,而且缺乏一本系统地介绍RxJava的中文书籍,所以给很多初学者带来了困扰,不少人浅尝辄止,放弃了深入学习和使用RxJava的机会,这十分可惜。本书作为一本入门书,比较适合RxJava的初学者以及对RxJava有初步了解并想要进一步学习RxJava的读者。
内容结构
本书第1章从响应式编程入手,介绍了RxJava及RxJava的组成部分,帮读者初步了解RxJava。
第2章配合官方的示意图分类介绍了RxJava的大部分操作符。这一章的篇幅比较多,读者在阅读的时候可能无法全部记住,可以在需要时随时翻阅查询。
第3章就各种Scheduler的特点和适合的使用场景做了介绍,帮助读者根据实际需要选择最合适的Scheduler。
只知道轮子怎么跑还不够,还有必要知道轮子是如何造的,第4章结合源码研究了RxJava的实现原理。了解原理一方面可以让我们避免用错操作符或者Scheduler,另一方面如果碰到RxJava中的bug,也有助于我们定位bug。发现bug后可以到GitHub上发起一个issue,而且最好能够提一个附带的pull request来修复这个bug。
第5章给出了一些实例和基于RxJava的开源库的使用示例,以帮助读者更好地将RxJava应用于实际开发中。
第6章介绍了RxJava 2相对于RxJava 1的改进之处,如果读者已经掌握了RxJava 1,那么RxJava 2也可以很容易地上手。
给初学者的建议
RxJava这种响应式编程方式跟大多数人习惯的命令式编程方式有较大的区别,所以初学者首先需要完成编程思想上的转变,理解RxJava的思想。如可以将Observable看作工厂的原材料生产机器,发送出来的数据即为原材料,整个链式操作可以视为原材料经过一条流水线,每个操作符为流水线上的一个车间,每个车间都会对原材料做一定的加工,最终的Subscriber可以视为最终消费者,会接收加工后的成品。
其次就是了解RxJava的操作符都有哪些,都有什么样的作用。你不需要一开始就将每个操作符都记住,但是可以大体上记住都有什么功能的操作符,这样在需要时就能够想起哪个操作符能够满足当下的需求。关于操作符的详细使用方式可以参阅第2章。
接下来就是实践环节了。初期可以尝试应用RxJava写一些小程序,并参阅网上的一些开源代码,看看别人都是怎么应用RxJava的。初步掌握之后就可以逐渐将RxJava引入到项目中,来解决一些工作过程中遇到的实际问题。只看不做永远都是眼高手低,只有将RxJava真正地应用到实际开发工作中,不断犯错、不断改进才能真正达到融会贯通的地步,才能真正地掌握RxJava的使用技巧。
最后,如果想要进一步学习RxJava,可以阅读源代码,可以深入地跟踪一个操作符的实现过程来了解其原理。如果有可能,可以参与到RxJava的bug修复或者新功能开发中,在GitHub上给RxJava提pull request,上面有很多大神会给你提各种修改意见,理解他们的思路绝对会让你受益匪浅。
读者服务
轻松注册成为博文视点社区用户(www.broadview.com.cn),扫码直达本书页面。
下载资源:本书如提供示例代码及资源文件,均可在 下载资源处下载。
提交勘误:您对书中内容的修改意见可在 提交勘误处提交,若被采纳,将获赠博文视点社区积分(在您购买电子书时,积分可用来抵扣相应金额)。
交流互动:在页面下方 读者评论处留下您的疑问或观点,与我们和其他读者一同学习交流。
页面入口:http://www.broadview.com.cn/33640
第1章 走进RxJava的世界
1.1 响应式编程
什么是响应式编程?响应式编程是一种以异步数据流为核心的编程方式。这里的数据一般是一些事件;而流则是在时间序列上的一系列的事件。任何东西都可以转化为数据流,如变量、用户输入事件、数据结构等。
我们可以很灵活地操纵数据流,如可以将两个甚至多个数据流融合成一个数据流,可以从数据流中过滤出感兴趣的事件,还可以将数据流中的事件转化为其他新的事件。数据流中的事件通常可以分成三种类型:普通事件、错误事件和结束事件。以用户的键盘输入事件为例,当用户依次敲击“A”、“B”、“C”键的时候,就会产生三个输入事件,计算机接收到这些事件并对其做出响应——将字母“A”、“B”、“C”显示在显示器上。当用户敲击回车键时,可以将其作为一个结束事件来表示数据流的结束,即用户输入结束。而在输入过程中发生的任何错误都可以作为数据流中的错误事件。
我们为什么要使用响应式编程呢?考虑这样的一种场景:用户登录一个购物客户端,这时客户端会将自己的用户名和密码通过网络请求发送出去,然后通过注册一个回调接口来监听请求的结果,因为结果只有成功和失败两种,所以回调里需要有onSuccess和onError两个接口来分别处理这两种情况,如代码1-1-1所示。
代码1-1-1
通过注册一个回调接口来监听请求的结果,这其实也算一种响应式编程了。如果在登录成功后,我们要根据用户的ID来请求用户的购物记录,又该怎么办呢?很明显,应该在onSuccess方法里面继续请求。同登录请求一样,也需要注册一个回调接口来监听请求的结果,让我们继续在代码1-1-1的基础上添加代码,如代码1-1-2所示。登录成功后我们发出了查询购物记录的请求,并在onSuccess方法里将购物记录展示到UI上面。
代码1-1-2
到这一步感觉还不错——除了有回调的嵌套外。如果我们有更进一步的需求:要求只展示最近一个月的购物记录(不考虑服务器端的实现),该怎么办呢?看来只能继续在onSuccess方法里改了,如代码1-1-3所示。为了看起来简单,我们忽略了外层的嵌套。
代码1-1-3
新的需求又来了:每条购买记录里可能包含多个物品,之前只展示了每条购买记录,现在我们需要将所有购买记录里的所有物品都展示到UI上。继续改,如代码1-1-4所示。
代码1-1-4
终于再次改完了,但是还可能有其他需求出现,如只显示金额大于100元的物品、将所有相同的物品合并后显示、有些物品需要请求网络获取更详细的信息,等等。看到这里,你会不会很崩溃?传统的命令式编程在处理这样的需求时就是非常痛苦的,但是使用响应式编程就可以游刃有余地处理。如果使用响应式编程,这些要求可以很容易地串成一条链式调用,如图1-1-1所示。读者可能不是很理解图中每一步的操作符是什么意思,不要担心,相信你读完本书后就可以很轻松地将该图中的链式调用实现出来。
图1-1-1
通过上面的实例和图1-1-1,我们可以看到响应式编程提高了代码的抽象层级,所以我们只需要关注与业务逻辑相关的事件,而不必去纠缠里面的一些细节。不仅如此,响应式编程的链式调用还可以消除回调嵌套,所以使用响应式编程写出来的代码往往会更加简明易懂。响应式编程非常适合以下几种情况:
1.鼠标的点击、移动事件,键盘的输入事件,移动设备上的各种触摸和手势事件。
2.当用户的位置改变时,其移动设备上的GPS信号和陀螺仪信号。
3.各种耗时的操作,如读取硬盘内容以及从网络请求数据,这些操作一般都是异步的。
4.涉及数据的转化、组合、过滤等操作的场景。
1.2 什么是RxJava
RxJava是一个非常著名的开源库,是ReactiveX(Reactive Extensions)的一种Java实现。ReactiveX是一种响应式扩展框架,有很多种实现,如RxAndroid、RxJS、RxSwift、RxRuby、RxCpp、RxGo等。最近几年RxJava在Java和Android的开发中得到了广泛的使用。截至本书写作时,RxJava在GitHub上已经超过28000个Star,想来突破30000也不是很遥远的事情。目前RxJava有1.x和2.x两个主要的分支,分别代表着RxJava 1和RxJava 2。由于RxJava 1发布的时间较早,使用也更广泛,所以本书的内容主要是针对RxJava 1的。但是RxJava 2已经发布,以后也会逐渐流行起来,所以在本书的最后一章会对RxJava 2做一些简单的介绍。
RxJava可以看作由Observable、Subscriber和Scheduler组成的,它们的关系如图1-2-1所示。Subscriber订阅到Observable,Observable会在默认或者指定的Scheduler上工作并产生数据流返回给Subscriber,Subscriber也会在默认或者指定的Scheduler上接收Observable发送过来的数据流。Scheduler是对线程的一种抽象,不同的Scheduler代表了不同的线程。
图1-2-1
1.3 Observable和Subscriber
Observable和Subscriber是RxJava的重要组成部分。Observable提供了subscribe方法,当有Subscriber通过subscribe方法订阅到Observable时,Observable就可以向Subscriber发送数据流。在1.1节中我们了解到响应式编程中的事件分为三类:普通事件、错误事件和结束事件,在Subscriber中有三个方法与这三种事件一一对应,Observable会通过调用Subscriber的这三个方法来发送对应的事件。
1.onNext:当Observable要发送普通事件时,就会调用这个方法。这个方法可以被调用0~N次。
2.onError:当在Observable内部有异常或者错误产生的时候,就可以调用这个方法来向Subscriber发送错误事件。这个方法只能被调用1次。
3.onComplete:如果Observable已经发送完所有的数据,并且没有发生错误,这时就需要调用这个方法来向Subscriber发送结束事件。这个方法也只能调用1次,而且和onError是互斥的关系,也就是说调用了onError后就不能调用onComplete,反之亦然。在onError或者onComplete被调用之后,Observable就失去了作用,不能再调用onNext来发送数据了。
Subscriber还提供了unsubscribe方法,当Subscriber订阅到Observable之后,可以随时调用这个方法来终止对Observable的订阅。
代码1-3-1定义了一个方法,该方法创建一个Observable并将其返回。创建的Observable会发送随机生成的5个小于10的整数。当生成的随机数大于8时,我们假设有了异常,然后调用onError抛出一个异常。
代码1-3-1
接下来建立一个Subscriber对象并将其注册给创建的Observable对象,然后接收其发送来的数据,参见代码1-3-2。其中log函数是自定义的函数,会将结果输出。
代码1-3-2
多测试几次会产生不同的结果,例如下面是测试两次的结果,第一次顺利发送完了5个数据,第二次在发送了3个数据后产生了错误。
除了上面这种通用的Observable之外,还有两种特殊的Observable,同样也可以产生并发送数据,它们分别是Single和Completable,与之分别对应的Subscriber是SingleSubscriber和CompletableSubscriber。
1.3.1 Single:单个数据的生产者
Observable产生的是一系列的多个数据,但是在很多情况下我们只需要一个数据,如使用Get方法从网络接口读取数据等,在这种情况下就可以使用Single来代替Observable进行数据的发送。Single同Observable类似,能够产生并发送数据和事件。但是不同于Observable可以发送无穷多的数据,Single只能发送一个数据或者一个错误事件。Single虽然也可以接受Subscriber的订阅,但是基于Single的特点,一般使用SingleSubscriber订阅。Single会调用SingleSubscriber的两个方法来发送数据和事件。
1.onSuccess:发送Single唯一的数据,只能调用一次。
2.onError:Single内部有异常或者错误时,调用此接口发送异常事件,同样只能调用一次。
同Observable一样,Single可以使用非常丰富的操作符(在第2章中会详细介绍各种操作符),其对大部分操作符的使用方式也和Observable类似。有些操作符可以让Single和Observable互相转化。代码1-3-3创建了一个Single对象,并对其进行订阅,订阅后会输出结果“1”。
代码1-3-3
代码1-3-3只发送了一个数据,代码1-3-4不会发送数据,而是会发送一个错误事件,订阅后就会输出结果“Single error”。
代码1-3-4
1.3.2 Completable:单个事件的生产者
通过1.3.1节我们了解了Single,它能够产生并发送数据。但是在有些情况下我们不需要数据,只需要关心结果是成功还是失败,如使用Put方法将数据上传到网络服务器,我们只关心上传是否成功,而不关心数据本身。在这种情况下我们就可以使用Completable。Completable与Single的不同之处在于,其只会发送错误和结束的事件,而不发送数据。Completable通过调用CompletableSubscriber的以下三个方法来发送事件。
1.onComplete:在Completable的工作顺利完成后,就可以调用此方法来发送结束事件。
2.onError:当Completable内部有异常或者错误产生时,调用此方法来发送错误事件。
3.onSubscribe(Subscription d):Completable可以调用此接口来返回一个Subscription对象,通过此对象可以取消对Completable的订阅。
与Observable类似,Completable同样有很多的操作符可以使用,也有一些同Observable和Single进行转化的操作符。下面的代码创建了两个Completable对象并分别对其进行订阅,代码1-3-5会输出“Completable error”,而代码1-3-6则会输出“onCompleted”。
代码1-3-5
代码1-3-6
1.4 在Android工程中引入RxJava
RxJava现在被广泛应用到了Android和Java开发中,如果想在Andorid工程中使用RxJava的话,只需要在Gradle配置文件中加入对RxJava的依赖。笔者写这本书的时候,RxJava的最新版本是1.3.3,因此可以通过下面的配置来加入对RxJava 1.3.3的依赖。
但是在Android开发中一般会添加对RxAndroid的依赖,而RxAndroid已经依赖于RxJava,并且一般难以及时更新到最新版的RxJava,所以如果要使用RxAndroid和最新版的RxJava,则可以通过下面的配置来导入依赖。
由于RxJava 2早已发布,你可能想直接用RxJava 2,这时可以通过下面的配置来导入对RxJava 2的依赖,其中x和y可根据RxJava 2的发布情况来随时更新,以获取最新版本的RxJava 2。
第2章 RxJava中的操作符
丰富的操作符是RxJava功能强大的体现之一。所谓的操作符其实就是一系列的函数,这些函数接收Observable<T>类型的输入,生成Observable<R>类型的输出,这里T和R可以相同也可以不相同。因为输入和输出都是Observable类型的,所以多个操作符可以共同形成链式调用,让程序的逻辑操作非常简明。
通常情况下,只要业务稍微复杂点,Observable产生的数据就不能直接满足Subscriber的需求。如从网络请求的数据可能是json格式的原始数据,在程序中不能直接拿来用,而需要将其转化成对应的Bean,然后发送到Subscriber,这样就可以直接用来做更新UI等操作。所以要想灵活地运用RxJava来处理各种各样的业务需求,熟练掌握操作符是十分有必要的。接下来将按照操作符的不同功能分类来讲解一下常用的操作符。[1]
2.1 创建Observable的操作符
其实在第1章中我们已经用到了一种创建Observable的操作符了,那就是create。在平时创建Observable时不推荐直接使用create操作符,推荐优先使用其他的操作符。这是因为使用create创建的Observable可能会因为不满足RxJava的规范而造成一些潜在的不稳定因素,比如发送数据和事件前没检查Subscriber的状态,调用onError之后又调用了onComplete,工作完成后忘记调用onComplete等。接下来我们来看一下其他用于创建Observable的操作符。
2.1.1 range
顾名思义,range操作符创建的Observable将会发送一个范围内的数据,其示意图如图2-1-1所示。
图2-1-1
从示意图中可以看到,range操作符接收两个参数n和m,创建的Observable将依次发送从n开始的m个数。需要注意的是,最后一个数为n+m-1,而不是n+m。代码2-1-1使用range操作符创建了一个Observable,对其订阅后就会输出10~14的5个整数。
代码2-1-1
2.1.2 defer和just
defer操作符的示意图如图2-1-2所示,只有当有Subscriber来订阅的时候才会创建一个新的Observable对象,也就是说每次订阅都会得到一个刚创建的最新的Observable对象,这可以确保Observable对象里的数据是最新的。其特点将在后面和just操作符对比讲解。
图2-1-2
just操作符接收某个对象作为输入,然后会创建一个发送该对象的Observable。这个对象可以是一个数字、一个字符串、数组、Iterate对象等。just是一种非常快捷的创建Observable对象的方法,在后面的例子里将会大量使用,示意图如图2-1-3所示。
图2-1-3
代码2-1-2通过两个方法创建两个Observable,这两个Observable都会将Android系统中的当前时间作为数据发送。我们将这两个 Observable 分别保存在变量 deferObservable 和justObservable中。
代码2-1-2
现在在两个Button的点击事件里分别对这两个Observable进行订阅,如代码2-1-3所示,多次点击Button就会实现多次订阅的效果。请读者先思考一下多次订阅后deferObservable和justObservable发送的数据会有什么样的差异。
代码2-1-3
输出结果如下所示,可以看到defer每次订阅都会得到Observable发送的一个全新的当前时间,而just创建的操作符即使订阅多次也都会发送出和首次订阅一样的数据。
2.1.3 from
from操作符接收一个对象作为参数来创建Observable,这个参数对象可以是Iterable、Callable、Future和数组等,其示意图如图2-1-4所示。from操作符创建的Observable将发送参数对象里的数据,其创建方式类似于just操作符,但是just操作符创建的Observable会将整个参数对象作为数据一下子发送出去。比如说参数对象是一个含有10个数字的数组,使用from创建的Observable就会发送10次,每次发送一个数字,而使用just创建的Observable会一次就将整个数组发送出去。
图2-1-4
代码2-1-4首先创建了一个数组和一个List,分别存储0~5的整数,然后使用from操作符分别以数组和List作为输入参数创建两个Observable对象。之后分别对这两个Observable对象进行订阅,会输出什么结果呢?
代码2-1-4
程序运行后的输出结果如下所示,通过from操作符创建的Observable对象将数组和List中的整数依次发送了出来。
2.1.4 interval
interval所创建的Observable对象会从0开始,每隔固定的时间发送一个数字。需要注意的是,这个对象是运行在computation Scheduler(Scheduler将会在第3章中进行讲解)中的,所以在Android开发中,如果需要在UI中显示结果,则要在主线程中订阅。interval操作符的示意图如图2-1-5所示。
图2-1-5
代码2-1-5通过interval操作符创建了一个Observable,创建的Observable将会以1秒为间隔不断地发送数据,因为我们需要更新 UI,所以需要在主线程中进行订阅。这里的AndroidSchedulers.mainThread()属于RxAndroid库,RxAndroid是Jake Wharton在Android平台上开发的一个对RxJava的扩展。最后创建一个Subscriber对象对这个Observable对象进行订阅,就会每秒输出一个从0开始递增的数据。
代码2-1-5
由于interval操作符创建的Observable对象会不停地发送数据,所以当我们不再需要它的数据时不要忘记调用unSubscribe方法进行反订阅,反订阅后Observable将会停止发送数据。
2.1.5 repeat和timer
repeat操作符可以让Observable对象发送的数据重复发送N次,我们可以指定其发送的次数,其示意图如图2-1-6所示。
图2-1-6
timer操作符创建的Observable会在指定时间后发送一个数字0,注意其默认也是运行在computation Scheduler上,其示意图如图2-1-7所示。
图2-1-7
下面我们来创建一个发送整数1、2、3的源Observable,并使用repeat操作符在源Observable的基础上创建一个新的Observable,使其重复发送数据3次。另外使用timer创建一个会在1秒后发送数据的Observable,如代码2-1-6所示。
代码2-1-6
接下来,分别对这两个Observable进行订阅,如代码2-1-7所示。
代码2-1-7
结果如下所示,可见repeat操作符让源Observable发送的数据重复发送了3遍;timer操作符创建的Observable在订阅1秒后发送了一个数据0。
至此创建Observable的操作符就基本讲完了,还有几个非常简单的创建操作符,如naver、empty、throw等,在这里就不赘述,感兴趣的读者可以查看官方文档。
2.2 转化Observable的操作符
在2.1节中,我们了解了如何创建Observable。如果说创建Observable是运用RxJava的基础的话,那么转化Observable则是其主干。在通常情况下,创建一个Observable只是完成了工作的第一步,要想完成一些复杂的工作场景,往往还需要将创建的Observable按照一定规则进行转化。在本节中我们来了解一下如何转化Observable。
2.2.1 buffer
顾名思义,buffer操作符所要做的事情就是将数据按照规定的大小做一下缓存,当缓存的数据量达到设置的上限后就将缓存的数据作为一个集合发送出去。如示意图2-2-1所示,里面的buffer的大小为3,因此每缓存3个数据就会将这3个数据作为整体发送出去。
图2-2-1
buffer操作符还可以设置跳过的数目。如图2-2-2所示,我们加入了一个skip参数,用来指定每次发送一个集合需要跳过几个数据。图中指定的count为2,skip为3,这样就会每隔3个数据发送一个包含2个数据的集合。如果count大于或者等于skip的话,skip就失去了效
....
本站仅展示书籍部分内容
如有任何咨询
请加微信10090337咨询