1. 前言
思考再三,还是先写一篇关于网络通信的博客。说起网络通信,可能你首先会想到一系列的网络通信的协议,这里不讲这些,这里只讲开发时候会使用到的网络通信框架的一些理解:RxJava+Retrofit+OkHttp。
2. 框架设计原理
一个优秀的框架具备高性能,高解耦合,通常会结合各种设计模式,以及MVP的架构来进行封装,其中网络框架的设计还需要结合这三个开源库:RxJava,Retrofit,OkHttp。
其中可能最被熟悉的开源库就是OkHttp了,但随着发展,Square公司又开发了一个新的网络请求框架,那就是Retrofit。Retrofit是基于OkHttp的,它底层的所有请求默认走的都是OkHttp。它在OkHttp的基础上进一步封装,使用注解方式让我们使用简单方便且看代码一目了然。Retrofit是基于APP发起请求的封装,也就是面向的是应用层(比如响应数据的处理和错误处理等)。而OkHttp是对底层网络请求的封装与优化(socket优化,数据压缩,buffer缓存等)。
如果说Retrofit是OkHttp的进化版,更加解耦,更加简单的话,那RxJava又有什么作用呢?
可能大家在android中都会接触到异步两种常用方式:AsyncTask 和Handler ,RxJava的作用也跟这两者相同,也是一种异步方式。但RxJava的话会更加简洁,在越复杂的场景下使用,越会感觉到RxJava的简。
所以我们这个网络框架使用到的三个开源库的分别作用是:
RxJava:提供一种简洁的异步方式
Retrofit:以注解方式发起请求,本质也是基于OkHttp发起网络请求的
OkHttp:对底层网络请求的封装与优化
3. 实例开发第一步
直接上手,一个字,干!
第一步其实很简单,就是在build.gradle项目文件中添加引入各种库配置:
/** rxjava **/
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
/** retrofit **/
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
/** okhttp **/
compile 'com.squareup.okhttp3:okhttp:3.3.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
4. 实例开发第二步
第二步很简单,但千万不要忘了,需要这AndroidManifest.xml文件中声明权限:
<uses-permission android:name="android.permission.INTERNET" />
5. 实例开发第三步
直接上核心代码:
private void doRequestByRxRetrofit() {
initOkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wthrcdn.etouch.cn/")//基础URL,建议以 / 结尾
.client(mOkHttpClient)//自定义client,可以不选,底层默认带有
.addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器,自动给你转好了json,很方便
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//RxJava 适配器
.build(); //创建retrofit 实例
//create之后自动转RxWeatherService 类型
RxWeatherService rxJavaService = retrofit.create(RxWeatherService.class);
rxJavaService.getMessage("北京")
//subscribe过程发生在io线程中,这里的参数可选其他
.subscribeOn(Schedulers.io())
//Subscriber过程发生在UI线程中,也就是onNext这个回调最后会发生在UI线程中,所以可以做更新UI操作
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<WeatherEntity>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(WeatherEntity weatherEntity) {
//获取数据,更新UI
showMsg.setText("response ==" + weatherEntity.getData().getGanmao());
}
});
}
private void initOkHttpClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
if (mOkHttpClient == null) {
synchronized (MainActivity.class) {
if (mOkHttpClient == null) {
// 指定缓存路径,缓存大小100Mb
Cache cache = new Cache(new File(getExternalCacheDir(), "HttpCache"),
1024 * 1024 * 100);
mOkHttpClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
}
}
}
}
RxWeatherService接口代码如下:
public interface RxWeatherService {
@GET("weather_mini")
Observable<WeatherEntity> getMessage(@Query("city") String city);
}
完整的请求地址是:http://wthrcdn.etouch.cn/weather_mini?city=北京
这里显然是以GET方式请求网络,参数weather_mini后面接了个“?”,这是一个查询参数,即查询key为city对应的value的值。这其实就是解析一组json数据!
以及附带的实体类代码:
public class WeatherEntity {
private DataBean data;
private int status;
private String desc;
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static class DataBean {
private YesterdayBean yesterday;
private String city;
private String aqi;
private String ganmao;
private String wendu;
private List<ForecastBean> forecast;
public YesterdayBean getYesterday() {
return yesterday;
}
public void setYesterday(YesterdayBean yesterday) {
this.yesterday = yesterday;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAqi() {
return aqi;
}
public void setAqi(String aqi) {
this.aqi = aqi;
}
public String getGanmao() {
return ganmao;
}
public void setGanmao(String ganmao) {
this.ganmao = ganmao;
}
public String getWendu() {
return wendu;
}
public void setWendu(String wendu) {
this.wendu = wendu;
}
public List<ForecastBean> getForecast() {
return forecast;
}
public void setForecast(List<ForecastBean> forecast) {
this.forecast = forecast;
}
public static class YesterdayBean {
private String date;
private String high;
private String fx;
private String low;
private String fl;
private String type;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFx() {
return fx;
}
public void setFx(String fx) {
this.fx = fx;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFl() {
return fl;
}
public void setFl(String fl) {
this.fl = fl;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
public static class ForecastBean {
private String date;
private String high;
private String fengli;
private String low;
private String fengxiang;
private String type;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFengli() {
return fengli;
}
public void setFengli(String fengli) {
this.fengli = fengli;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFengxiang() {
return fengxiang;
}
public void setFengxiang(String fengxiang) {
this.fengxiang = fengxiang;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
}
}
通过上面的内容你就可以构建一个简单的基于RxJava+Retrofit+OkHttp的网络请求框架了,已对关键处做了注释。
但上面的代码主要是让你熟悉RxJava+Retrofit+OkHttp三者联系,实际开发中内容会更加的丰富。
6. 后记
再提一下,上面只是很简单的内容,无论RxJava,Retrofit,OkHttp哪一个开源库,都是值得研究的,里面有丰富与成熟使用的设计模式,我猜这篇文章你肯定没有看爽,时间充裕的情况下大家可以去啃一下,很有意思的,嘿嘿。