咱们接着上一篇文章来讲,没看过第一篇的可以先回顾一下flatmap和mergeWith的两个例子
今天我们来分析一下Ben大神在Goto大会上分享的一个Netflix里面的例子。视频在此,可以翻墙的同学好好看。另外我自己尝试按照Ben的思路写了一个实例代码,在我的github上:
https://github.com/richardissuperman/netflixrxexample
先上一张图,是这个例子的结构:
总体的结构大家可以看到,netflix的用例里面,一共进行了四层转换。
他们是用来干嘛的?
一脸懵逼那我们来一步步分析这四层转换到底做了些什么。
注1:图中的mayMany其实就是flatmap
注2:图中三个子Obervable还有进行一次map转换,在我的代码中省略了这一步。
首先,先交代一下例子背景。
1.假设我们需要通过一个用户的userId,执行queryA获取他/她所关注的视频列表,列表中的对象是Video类型对象,返回值是Json格式的string。
2.获取了列表之后我们只需要获取前10个Video对象。
3.非常不幸的事情是,我们获取的Video对象不是一个完整的Video对象,queryA返回的值还缺少了三个类成员->Rating, Metadata和BookMark.。所以我们得通过Video对象的Id,call三个不同 api来获取缺失的三个值,再讲他们重新填入对应的Video对象。
真麻烦!都不知道如何下手了,如果没有RxJava的话,大家可以试想一下怎么实现
一百脸茫然那么针对上面的需求我们可以整理一下思路,每一步究竟要做什么:
Step1:通过userId获取video的数据,这个时候我们需要一个Observable<Video>
Step2:取前10个对象,这里实现很简单,take(10)足矣,依然是返回Observable<Video>。
Step3:这一步需要我们进行nested callback了,因为每一个Video对象我们都需要进行三个额外的API call,去获取Rating,MetaData和Bookmark。但是这三个call都是同一时间进行的。所以我们在这一步可以通过flatmap把Step2里面产生的Observable转换成多个(分别是Observable, Observable 和 Observable),并且整合上述三个api call结果并且生成一个新的Observable<Video>返回。
Step4:在Step3中怎么整合?试试zip() 这个操作符吧!简单的说就是把若干不同的Obervable整合成一个Observable。比如我们最终需要一个A对象,然后A由B和C对象组成,那么假如我们有一个Observable<B>和Observable<C>的话,就可以把这两个Observable zip一下整合成一个Observable<A>。
zip()因为我们需要将三个Api call的结果整合在一起(Rating,MetaData,Bookmark)生成一个Video,所以我们这里选择可以用zip()。
我们先上代码,分别是Video类,VideoService类
video类Video类的实现比较简单,只是单纯的加入了几个class member。但是注意MetaData, BookMark, Rating这三个member是有getObservable方法的。
接下里是VideoService类
可以看第一个方法是根据UserId返回原始Video对象的Observable,剩下三个则是根据videoId获取bookmark,rating,metadata的Observable的方法。他们基本上都是差不多的。
那么在定义好这些方法之后我们要开始调用他们了,调用代码如下:
开始啦我们挑重点一行行解释
line 26 ->根据userID返回一个Observable<Video>,此时返回的video对象都是不完整的
line 28 ->只选取10个
line 30 ->这里我们需要返回一个新的Observable<Video>, 由 line 35- 37的三个Observable zip() 而成
line 39 - 53 ->三个子Observable互相zipWith(),每次zip都在原来video对象上填充需要的member。
line 57 -> 我们在安卓的主线程里面handle收到的新Video对象。
我相信在分析完这两篇用例之后大家应该会有种感觉,在以往的异步编程,尤其是涉及多任务交互时,我们实际编写的代码和脑袋中的抽象思维往往是不一致的,因为我们需要决定怎样改变线程,怎么样遍历collection等等code里面的细节。而RxJava却改变了这一个问题,你解决问题的思路是怎么样,那么实际代码就是怎么样。就比如想这次的netflix的例子,所有的code都是根据我们在编写代码之前所构思的一样,顺着下来的。所以我的观点是RxJava可能在performance上面并不能改变多少,但是它带给程序员的是思考编写代码上的便利,你的抽象,解决问题的思路是怎么样,你的程序就是怎么样,某种程度上增加了代码的可读性(当然如果一个完全没接触过RxJava的程序员肯定是一脸蒙蔽)
到此,netflix的这个例子已经分析完毕了,有兴趣的朋友可以去我的github repo好好看看代码仔细研究一下。https://github.com/richardissuperman/netflixrxexample
下周我会着重分析一下RxJava在安卓开发中的使用例子。
网友评论
https://github.com/richardissuperman/netflixrxexample