零、背景
比起阅读枯燥的技术文档,独自苦苦摸索新技术的基本用法,还有一种更好更快速也更有效的提高自身技术的方法,那就是阅读学习优质的开源项目,通过仿写、练习最终达到理解,潜移默化提升自身编程技能。
《带你学开源项目》系列将带领你深入阅读及分析当前流行的一些开源项目,并针对其中采用的新技术与精妙之处进行细致的阐述,以期让你快速掌握Android开发中的多种强大技能点。
一、本期开源项目Meizhi Android
本次的开源项目选择了Meizhi Android,本文主要介绍该项目中采用的RxJava
、Retrofit
两种技术,这二者在Android开发者中非常流行,不仅能够优美地处理异步回调
,而且能提高代码的性能和稳定性
。而Meizhi Android中较好的覆盖了二者的多种应用场景,能够给多数开发者一个全面的学习。
下面本人会对原项目的代码进行详细的介绍
,同时为了读者看的清楚其中的逻辑关系,可能会做一定调整以帮助读者理解,比如把lambda表达式还原成普通java函数形式,以避免很多读者对lambda并不熟悉。
二、原项目分析
0. clone项目到本地
第一步当然是把项目clone下来,编译,运行。有兴趣的同学可以执行这一步。
1. 添加Stetho
抓包工具
首先,由于我们要分析retrofit,所以为了查看app的网络请求,有兴趣的同学可以手动在代码里添加Stetho。Stetho
是Facebook推出的一款黑科技,能够在chrome里轻松查看app所有的网络请求,比起iOS需要装个Charles查看http请求方便多咯。
2. Retrofit结构
从下图我们可以看到,首页里有很多card,每一个card里有两个元素:妹纸图片
, 描述文字
,具体UI实现我们不在乎,只要明白一点,这两个元素数据是来自于两个不同的api。其中,妹纸图片
来自于http://gank.io/api/data/福利/10
;描述文字
来自于http://gank.io/api/data/休息视频/10
。
app中为了请求网络数据,采用了Retrofit。具体关于retrofit如何配置请各位参考官网,这里只讲解如何使用Retrofit
。
该项目中主要创建了以下几个类来实现Retrofit
结构,大家可以作为参考用于自己的项目中。
i. GankApi
:这个类用来定义相关的http
接口,这是符合retrofit规范的定义形式,每一个api返回的为Observable
格式结果,方便RxJava
进行进一步处理。
1 2 |
@GET("/data/福利/{page}") Observable getMeizhiList(@Path("page") int page); @GET("/data/休息视频/{page}") Observable getGankVideoList(@Path("page") int page); |
ii. DrakeetRetrofit
:这个类用来对Retrofit
进行相关配置并生成GankApi
实例gankApi
1 2 3 4 5 6 7 8 9 10 11 12 |
OkHttpClient client = new OkHttpClient(); RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setClient(new OkClient(client)) .setLogLevel(RestAdapter.LogLevel.FULL) .setEndpoint("http://gank.io/api") .setConverter(new GsonConverter(gson)); RestAdapter gankRestAdapter = builder.build(); GankApi gankApi = gankRestAdapter.create(GankApi.class); public GankApi getGankApi() { return gankApi; } |
iii. DrakeetFactory
: 这个类用来对外生成单例GankApi
实例,为确保GankApi
实例只生成一次。
1 2 3 4 5 6 7 8 9 10 |
public static GankApi getGankApi() { if (sGankApi == null) { synchronized (monitor) { if (sGankApi == null) { sGankApi = new DrakeetRetrofit().getGankApi(); } return sGankApi; } } } |
所以,在实际应用场景中,比如我们想要发起一个http请求来获取福利
数据,那么我们可以采用以下方式:
1 2 |
GankApi gankApi = DrakeetFactory.getGankApi(); Observable meizhiList = gankApi. getMeizhiList(10); |
3. 首页的RxJava的实现
既然我们已经把网络框架搭建好了,那么可以开始从服务器获取数据并显示了。我们首先看首页的数据。下面,我来对首页数据进行分析,一步步推出所需要的RxJava表达式。
上面已经介绍过,每一个card里有两部分数据:妹纸图片
(红色方框)和描述文本
(绿色方框)。
妹纸图片
数据来自于"/data/福利/{page}"
这个api,该api会返回妹纸图片的url;描述文本
来自于"/data/休息视频/{page}"
这个api,该api会返回休息视频及相关描述信息,card里会把描述信息显示出来;- 两个api均可以携带
page
字段,即一次请求可以获得多个数据。如我们在"/data/福利/{page}"
里设置page=10
,那么我们一次请求可以得到10条福利
数据,即10张妹纸图片url
; - 由于我们一次可以获得多张妹纸图片url和多个视频信息,那我们就需要把
二者进行合并
,即单拎出来一张妹纸图片和一个视频信息组装成一个card
。然后按这种方式生成其他的card。
小结一下,根据以上描述,假如我们把两个api的page都设置为10
,那么两个请求同时发出去后,我们能得到10张妹纸图片url
(如http://img.com/1.png
, http://img.com/2.png
, …)和10个视频信息
(如舌尖上的中国
, 星际穿越
, …),然后我们将二者组装成10个card所需要的数据
,放入每个card里显示即可。
好,终于可以开始动手写代码了。上面的分析看似复杂,然后只要你学会了如何分析,很快就能写出对应的RxJava代码。下面我结合RxJava的数据流思想
和具体操作符
来介绍实现代码。
i. 在网络请求数据之前,我们要创建几个数据entry对象来将获取回来的json字符串转化为object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
起阅读枯燥的技术文档,独自苦苦摸索新技术的基本用法,还有一种更好更快速也更有效的提高自身技术的方法,那就是阅读学习优质的开源项目,通过仿写、练习最终达到理解,潜移默化提升自身编程技能。
《带你学开源项目》系列将带领你深入阅读及分析当前流行的一些开源项目,并针对其中采用的新技术与精妙之处进行细致的阐述,以期让你快速掌握Android开发中的多种强大技能点。 一、本期开源项目Meizhi Android本次的开源项目选择了Meizhi Android,本文主要介绍该项目中采用的 下面本人会 二、原项目分析0. clone项目到本地第一步当然是把项目clone下来,编译,运行。有兴趣的同学可以执行这一步。 1. 添加
|
1 2 |
@GET("/data/福利/{page}") Observable getMeizhiList(@Path("page") int page); @GET("/data/休息视频/{page}") Observable getGankVideoList(@Path("page") int page); |
ii. DrakeetRetrofit
:这个类用来对Retrofit
进行相关配置并生成GankApi
实例gankApi
1 2 3 4 5 6 7 8 9 10 11 12 |
OkHttpClient client = new OkHttpClient(); RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setClient(new OkClient(client)) .setLogLevel(RestAdapter.LogLevel.FULL) .setEndpoint("http://gank.io/api") .setConverter(new GsonConverter(gson)); RestAdapter gankRestAdapter = builder.build(); GankApi gankApi = gankRestAdapter.create(GankApi.class); public GankApi getGankApi() { return gankApi; } |
iii. DrakeetFactory
: 这个类用来对外生成单例GankApi
实例,为确保GankApi
实例只生成一次。
1 2 3 4 5 6 7 8 9 10 |
public static GankApi getGankApi() { if (sGankApi == null) { synchronized (monitor) { if (sGankApi == null) { sGankApi = new DrakeetRetrofit().getGankApi(); } return sGankApi; } } } |
所以,在实际应用场景中,比如我们想要发起一个http请求来获取福利
数据,那么我们可以采用以下方式:
1 2 |
GankApi gankApi = DrakeetFactory.getGankApi(); Observable meizhiList = gankApi. getMeizhiList(10); |
3. 首页的RxJava的实现
既然我们已经把网络框架搭建好了,那么可以开始从服务器获取数据并显示了。我们首先看首页的数据。下面,我来对首页数据进行分析,一步步推出所需要的RxJava表达式。
上面已经介绍过,每一个card里有两部分数据:妹纸图片
(红色方框)和描述文本
(绿色方框)。
妹纸图片
数据来自于"/data/福利/{page}"
这个api,该api会返回妹纸图片的url;描述文本
来自于"/data/休息视频/{page}"
这个api,该api会返回休息视频及相关描述信息,card里会把描述信息显示出来;- 两个api均可以携带
page
字段,即一次请求可以获得多个数据。如我们在"/data/福利/{page}"
里设置page=10
,那么我们一次请求可以得到10条福利
数据,即10张妹纸图片url
; - 由于我们一次可以获得多张妹纸图片url和多个视频信息,那我们就需要把
二者进行合并
,即单拎出来一张妹纸图片和一个视频信息组装成一个card
。然后按这种方式生成其他的card。
小结一下,根据以上描述,假如我们把两个api的page都设置为10
,那么两个请求同时发出去后,我们能得到10张妹纸图片url
(如http://img.com/1.png
, http://img.com/2.png
, …)和10个视频信息
(如舌尖上的中国
, 星际穿越
, …),然后我们将二者组装成10个card所需要的数据
,放入每个card里显示即可。
好,终于可以开始动手写代码了。上面的分析看似复杂,然后只要你学会了如何分析,很快就能写出对应的RxJava代码。下面我结合RxJava的数据流思想
和具体操作符
来介绍实现代码。
i. 在网络请求数据之前,我们要创建几个数据entry对象来将获取回来的json字符串转化为object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |