前言
今天给大家分享的主题是网络请求框架,而今天的两位主角分别是retrofit和rxjava。这是我在我现在的工作项目中所运用的网络请求以及数据处理框架。我也观察到群里很多同学也接触了这两个框架,我分享的是我对这两个框架的浅见和使用心得,有不对和不足的地方希望能引起讨论。欢迎打脸!
我每次在接触一个新事物的时候,首先会在脑海里过三点:
1. what(它是什么?)
2. why(为什么用它?)
3. how(如何用它?)
通过这三个点,把点连成线,慢慢就会熟悉它,最后就可以整合进自己的知识库中。
what(它是什么?)
retrofit
它是square公司出产的又一个精品,它有着简易的接口配置、强大的扩展支持、优雅的代码结构等优质特点而受到广泛的欢迎。retrofit是一个RESTful风格的HTTP网络请求框架的封装。注意我这里并没有说是网络请求框架哦,主要原因是网络请求的工作并不是retrofit来完成的。retrofit2.0开始内置了OKHttp,前者专注于接口的封装,后者专注于高效的网络请求,二者分工协作。就好像OKHttp是一款牛B的发动机,而retrofit是完美的汽车外壳和零部件,它不止使发动机的优秀性能完美发挥,还能方便我们改装这辆汽车,成为我们的心爱之物。
rxjava
它是目前Android开发中热门的函数库。它专注于响应式编程,让异步事件以序列的形式组织代码。使你的思路能用清晰的代码实现。这里的关键点是响应式编程,我在这按下不表,大家有兴趣可以学习一下,能更方便你理解rxjava。
why(为什么用它?)
先给大家看一段代码,这是我在2014年刚参加工作的时候写的代码,图片中是定义了一个登录请求方法,需要传入请求参数和请求响应监听,请求框架用的是volley。在这里我简单介绍一些volley,它是Google在2013年推出的网络通信框架,它可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片。但是volley也有弊端,因为volley设计目标是非常适合去进行数据量不大,但通信频繁的网络操作,所以对于 大数据量的网络操作,比如说下载/上传文件等,Volley的表现就会非常糟糕。
这是请求方法的外部调用。第一个是登录请求方法的外部调用,然后下面是实例化了一个网络请求监听,里面的逻辑是解析json数据,并做登录相关逻辑,还得处理登录请求可能带来的异常。
这是对返回数据进行解析。
从上面的代码中可以看出一些弊端:
1. 比如我不想做烦琐的json解析工作了(fastjson这些咱暂时不用讨论),我想请求回来的数据能直接转换成bean对象
2. 错误处理的代码写得到处都是,我想有一个统一的管理
3. 为了防止服务器返回给我们坏数据,我们得做很多容错工作。
不止上面说的三点,后面工作中还遇到一些坑,比如:我在做文件上传的时候真的很头疼,因为volley不适合做文件上传工作,写了很多上传相关的代码;再比如说,当多个请求需要组成链式请求的时候,代码会写得很繁琐,后面我都不想看了。所以后期的维护工作做了很多,基本是自己挖坑自己踩。而且一个公认的事实是,OKHttp相对于volley来说,性能还是要高出不少。
当我正在为自己挖的坑而苦恼的时候,retrofit和rxjava这两个吊炸天的框架在国内慢慢流行起来,当我发现它能做什么,能解决我的许多实际问题的时候,心里面就在想:窝草?它还能这样?。这就是我为什么要用retrofit和rxjava的原因。
how(如何用它?)
当我们了解了它是什么,并且说服自己去使用它的时候,我们就要看看它是怎么玩的,那种姿势才是最佳体位。先给大家看一看我的网络请求所需要的几个基本类。
现在我们开始一步步搭建请求,我们在在HttpMethod类中构建retrofit。
结合rxjava创建一个请求observable,即被观察者。这里支持设定请求数据的模板。刚才说到了被观察者,就解释一下被观察者和观察者。在rxjava中,一个很重要的概念就是观察者模式。
用button来做比喻,observable是button的话,subscriber就是onclickListener。那他们的setOnclickListener方法是什么呢,我们后面再讲。
创建了观察者之后,我们就得制定一些订阅关系了。RxJava 可以使用subscribeOn和observeOn这两个方法完美处理被观察者和观察者的执行线程问题.
我们在没有使用框架做http请求的时候我们需要new一个线程,然后才开始请求,因为网络请求是耗时操作,而用了rxjava一切都变了只需一行代码轻松切换线程调度,而切换到主线程就类似于之前用handler的操作,因为操作ui不能子线程完成。这里就有很大的魅力了,以前的线程代码和headler代码这么多行,现在就两行了,并且还是链式调用,简单明了逻辑清晰。
好了,现在看一下请求方法的封装,我们先构建retrofit对象,然后设置请求参数,是以map的形式传递,然后实例化一个网络请求的被观察者(observable)并通过map修饰符,对基本数据类型转换成具体数据类型。最后再进行被观察者和观察者的订阅,就像button.setonclickListener()一样。可以看到我在map方法中,我实例化了一个叫HttpFunc的类,我来介绍一下这个类是干什么的。
我在HttpMethod中定义了一个内部类,实现了Func1接口,便于对数据做一些统一处理,把我们关心的具体数据部分剥离出来,而且还可以处理请求的异常。Func1是rxjava的一个有返回值的接口,作用是实现有数据的回调。
如何去用?
接下来就是外部调用请求方法啦,这里我传入了两个对象,一个是model的监听器,还有一个是网络请求的观察者,那他们是如何工作的呢?
首先先来看自定义观察者,也就是类似于button的onclicklistener,他继承了rxjava的subscriber(观察者),我在这里重写了父类的方法,以实现扩展。然后把传进来的自定义监听实例化,便于监听数据。
最后我们再来对比一下,改造前和改造后代码。
改造前Volley请求代码
改造后Retrofit+Rxjava代码
我们最后再来代码的前后对比,虽然代码看上去多了一些,但是稳定性高,逻辑严谨,方便扩展,比如你想添加拦截器等。而稳定性在于,如果有异常情况的话,RxJava的onError 方法会执行,这就方便我们统一去处理异常数据了,不用再担心服务器传出坏数据,导致程序崩溃了,一句服务器异常,就可以把锅扔给服务器了。
它不止能做这些,他还能做链路请求,以及上传文件等诸多复杂的逻辑。
我们在工作中都会面临需求变更,修改代码;但是你会发现,使用RxJava的方式,会降低出现bug的概率,而且就算是不同的人去改,也会比较方便维护。我现在用到的只是这两大神器的冰山一角,RxJava的存在不仅仅在于网络请求,可以用在别的方面;RxJava其实是体现了一种思路,所有对数据的操作都在流上完成,只返回给观察者所关心的数据。然后异常情况啊,多余数据啊都统统剔除掉了。
结束语
我以前常常看着我那一堆的if、else等迷之代码,好半天才能理清楚逻辑,知道写代码有条理是多么的重要。而RxJava+Retrofit 结合会让我们写代码的方式思路很清晰,有条理,虽然代码量会增多,但逻辑的清晰才是最重要,这是我的亲身体会。我对请求框架的封装肯定不是最优方案,而且有缺陷,希望大家多多讨论,互相学习。
最后给大家一个传送门,我就是参考这篇博客慢慢搭建起自己的请求框架的。
这是demo源码地址