Android 网络请求改造之路

oex2000 8年前
   <p>今天给大家分享的主题是网络请求框架,而今天的两位主角分别是retrofit和rxjava。这是我在我现在的工作项目中所运用的网络请求以及数据处理框架。我也观察到群里很多同学也接触了这两个框架,我分享的是我对这两个框架的浅见和使用心得,有不对和不足的地方希望能引起讨论。</p>    <p>我每次在接触一个新事物的时候,首先会在脑海里过三点:</p>    <ol>     <li> <p>what(它是什么?)</p> </li>     <li> <p>why(为什么用它?)</p> </li>     <li> <p>how(如何用它?)</p> </li>    </ol>    <p>通过这三个点,把点连成线,慢慢就会熟悉它,最后就可以整合进自己的知识库中。</p>    <p>what(它是什么?)</p>    <p>retrofit</p>    <p>它是square公司出产的又一个精品,它有着简易的接口配置、强大的扩展支持、优雅的代码结构等优质特点而受到广泛的欢迎。retrofit是一个RESTful风格的HTTP网络请求框架的封装。 <strong>注意我这里并没有说是网络请求框架哦</strong> ,主要原因是网络请求的工作并不是retrofit来完成的。retrofit2.0开始内置了OKHttp,前者专注于接口的封装,后者专注于高效的网络请求,二者分工协作。就好像OKHttp是一款牛B的发动机,而retrofit是完美的汽车外壳和零部件,它不止使发动机的优秀性能完美发挥,还能方便我们改装这辆汽车,成为我们的心爱之物。</p>    <p>rxjava</p>    <p>它是目前Android开发中热门的函数库。它专注于响应式编程,让异步事件以序列的形式组织代码。使你的思路能用清晰的代码实现。这里的关键点是响应式编程,我在这按下不表,大家有兴趣可以学习一下,能更方便你理解rxjava。</p>    <p>why(为什么用它?)</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/825e91d862e9371b8048b85376afb594.png"></p>    <p>先给大家看一段代码,这是我在2014年刚参加工作的时候写的代码,图片中是定义了一个登录请求方法,需要传入请求参数和请求响应监听,请求框架用的是volley。在这里我简单介绍一些volley,它是Google在2013年推出的网络通信框架,它可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片。但是volley也有弊端,因为volley设计目标是非常适合去进行数据量不大,但通信频繁的网络操作,所以对于   大数据量的网络操作,比如说下载/上传文件等,Volley的表现就会非常糟糕。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/201820bfd4d44166c04f7f00084087fb.jpg"></p>    <p>这是请求方法的外部调用。第一个是登录请求方法的外部调用,然后下面是实例化了一个网络请求监听,里面的逻辑是解析json数据,并做登录相关逻辑,还得处理登录请求可能带来的异常</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/9114f979c77d857f005832ba911b8843.jpg"></p>    <p>这是对返回数据进行解析。</p>    <p>从上面的代码中可以看出一些弊端:</p>    <p>1. 比如我不想做烦琐的json解析工作了(fastjson这些咱暂时不用讨论),我想请求回来的数据能直接转换成bean对象</p>    <p>2. 错误处理的代码写得到处都是,我想有一个统一的管理</p>    <p>3. 为了防止服务器返回给我们坏数据,我们得做很多容错工作。</p>    <p>不止上面说的三点,后面工作中还遇到一些坑,比如:我在做文件上传的时候真的很头疼,因为volley不适合做文件上传工作,写了很多上传相关的代码;再比如说,当多个请求需要组成链式请求的时候,代码会写得很繁琐,后面我都不想看了。所以后期的维护工作做了很多,基本是自己挖坑自己踩。而且一个公认的事实是,OKHttp相对于volley来说,性能还是要高出不少。</p>    <p>当我正在为自己挖的坑而苦恼的时候,retrofit和rxjava这两个吊炸天的框架在国内慢慢流行起来,当我发现它能做什么,能解决我的许多实际问题的时候,心里面就在想:窝草?它还能这样?。这就是我为什么要用retrofit和rxjava的原因。</p>    <p>how(如何用它?)</p>    <p>当我们了解了它是什么,并且说服自己去使用它的时候,我们就要看看它是怎么玩的,那种姿势才是最佳体位。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/15a6ef53b129ad846ac72d1a0d96fc81.png"></p>    <p>先给大家看一看我的网络请求所需要的几个基本类。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a1d78ae7d7758c12c428d9fdae7d0e5d.jpg"></p>    <p>一步步开始搭建,(添加一下所在类的图片)在HttpMethod类中构建retrofit,简单解释一下这两个转换器。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f72d9be5e2b602b1ca704f1793615008.png"></p>    <p>结合rxjava创建一个请求observable,即被观察者。这里支持设定请求数据的模板。刚才说到了被观察者,就解释一下被观察者和观察者。在rxjava中,一个很重要的概念就是观察者模式。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fd8bac9f09d9d2fa6f34434927c870fc.png"></p>    <p>用button来做比喻,observable是button的话,subscriber就是onclickListener。那他们的setOnclickListener方法是什么呢,我们后面再讲。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ca7130d138fe281808e31ea2c21ae731.jpg"></p>    <p>创建了观察者之后,我们就得制定一些订阅关系了。RxJava 可以使用subscribeOn和observeOn这两个方法完美处理被观察者和观察者的执行线程问题.</p>    <p>我们在没有使用框架做http请求的时候我们需要new一个线程,然后才开始请求,因为网络请求是耗时操作,而用了rxjava一切都变了只需一行代码轻松切换线程调度,而切换到主线程就类似于之前用handler的操作,因为操作ui不能子线程完成。这里就有很大的魅力了,以前的线程代码和headler代码这么多行,现在就两行了,并且还是链式调用,简单明了逻辑清晰。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6c108639db15536e60b04386f9dacb84.jpg"></p>    <p>好了,现在看一下请求方法的封装,我们先构建retrofit对象,然后设置请求参数,是以map的形式传递,然后实例化一个网络请求的被观察者(observable)并通过map修饰符,对基本数据类型转换成具体数据类型。最后再进行被观察者和观察者的订阅,就像button.setonclickListener()一样。可以看到我在map方法中,我实例化了一个叫HttpFunc的类,我来介绍一下这个类是干什么的。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/4fb556f24c578402642076d3282b6b2e.jpg"></p>    <p>我在HttpMethod中定义了一个内部类,实现了Func1接口,便于对数据做一些统一处理,把我们关心的具体数据部分剥离出来,而且还可以处理请求的异常。Func1是rxjava的一个有返回值的接口,作用是实现有数据的回调。</p>    <p>如何去用?</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/4f25dbcf04a3a2e8963862910ea21fdb.jpg"></p>    <p>接下来就是外部调用请求方法啦,这里我传入了两个对象,一个是model的监听器,还有一个是网络请求的观察者,那他们是如何工作的呢?</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ad8f3e14c23b2eb64ce518947fbbdea0.jpg"></p>    <p>首先先来看自定义观察者,也就是类似于button的onclicklistener,他继承了rxjava的subscriber(观察者),我在这里重写了父类的方法,以实现扩展。然后把传进来的自定义监听实例化,便于监听数据。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c33827e8fd2298823df5b3dd86e01841.jpg"></p>    <p>这就是我定义的model数据监听,它能监听到界面关心的具体data数据以及网络请求的异常。就像层层传递一样,把我们关心的数据一层层的往上抛。</p>    <p>最后我们再来对比一下,改造前和改造后代码。</p>    <p>改造前Volley请求代码</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6e59c31db2951b0831473f469b9d7ff1.png"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5526ccb1b4acdaa9988de24df0a43fda.jpg" alt="Android 网络请求改造之路" width="550" height="343"></p>    <p>改造后Retrofit+Rxjava代码</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/98a11537c1a79206d05464fd9194901c.png" alt="Android 网络请求改造之路" width="550" height="67"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a4aa432f506685c88ebb7c7b5e7fcf3a.jpg" alt="Android 网络请求改造之路" width="550" height="309"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fbede310ac52851519104615dd5f57d6.jpg"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/39f693fa20938f066697d654a46654ee.jpg" alt="Android 网络请求改造之路" width="550" height="153"></p>    <p> </p>    <p>来自:http://url.cn/45QdWig</p>    <p> </p>