1. 概述
上一期我们提了一下Volley,Okhttp,Retrofit到底应该选哪一个?但是的确目前第三方的网络框架比较多,也不知道再等个几十年会出什么样的,到时候我们可能还是要换,然而随着版本的迭代这是一个很头疼的事情,如果要更换更好的网络框架成本就比较高了,今天我们来看一下怎么样打造一套网络框架引擎,一方面为了封装,一方面为了方便切换网络框架。
所有分享大纲:2017Android进阶之路与你同行
视频讲解地址:http://pan.baidu.com/s/1pKWuZrX
2. 套路分析
一般在开发中我们往往还要根据需求对第三方的网络框架进行封装,如Okhttp、Volley、Retrofit等等。封装是为了更符合我们的项目需求,方便调用,这一步可能少不了,那么我们只需要思考怎么样才能做到任意切换网络框架呢?如果能够随意切换最好。
其实我们请求的数据的时候基本是类似的无非就是获取数据和显示数据,可问题就在于各大网络框架的套路不一样,所以只要解决这个问题就好了。那么这个时候我们只需要自己搞一个套路就好,我们Activity ->自己的套路 ->第三大网络框架遵循我们的的套路->第三大网络框架,但是这样是不是会有问题呢?可能会有些许问题,毕竟不是直接的血缘关系,但是只要代码好扩展,随着项目的推进是很好完善的。
3. 实现
自定义一套规则,目前可以简单点,当然也可以根据项目需求稍微复杂点 IHttpEngine:
/**
* Created by Darren on 2017/03/01
* Email: 240336124@qq.com
* Description: 网络引擎的规范
*/
public interface HttpEngine {
// post 提交
public void post(Context context, String url, Map<String, Object> params, HttpCallBack httpCallBack, boolean cache);
// get 提交
public void get(Context context, String url, Map<String, Object> params, HttpCallBack httpCallBack, boolean cache);
// 取消请求
// 下载文件
// 上传文件
// https添加安全证书
}
定义自己的套路HttpUtils:
/**
* Created by Darren on 2017/03/01
* Email: 240336124@qq.com
* Description:
*/
public class HttpUtils {
// 上下文
private Context mContext;
// 网络访问引擎
private static HttpEngine mHttpEngine = new OkHttpEngine();
// 接口地址
private String mUrl;
// 请求参数
private Map<String, Object> mParams;
// get请求标识
private final int GET_REQUEST = 0x0011;
// post请求标识
private final int POST_REQUEST = 0x0022;
// 请求的方式
private int mRequestMethod = GET_REQUEST;
// 是否缓存
private boolean mCache = false;
// 切换引擎
public void exchangeEngine(HttpEngine httpEngine){
this.mHttpEngine = httpEngine;
}
// 可以在Application中配置HttpEngine
public static initEngine(HttpEngine httpEngine){
this.mHttpEngine = httpEngine;
}
private HttpUtils(Context context) {
this.mContext = context;
mParams = new HashMap<>();
}
public static HttpUtils with(Context context) {
return new HttpUtils(context);
}
public HttpUtils url(String url) {
mUrl = url;
return this;
}
// 执行方法
public void execute(HttpCallBack httpCallBack) {
if (TextUtils.isEmpty(mUrl)) {
throw new NullPointerException("访问路径不能为空");
}
if (mRequestMethod == GET_REQUEST) {
get(mUrl, mParams, httpCallBack);
}
if (mRequestMethod == POST_REQUEST) {
post(mUrl, mParams, httpCallBack);
}
}
}
封装一个简单的事例OkhttpEnigne:
/**
* Created by Darren on 2017/03/01
* Email: 240336124@qq.com
* Description: OKHttp引擎
*/
public class OkHttpEngine implements HttpEngine {
private static OkHttpClient mOkHttpClient = new OkHttpClient();
@Override
public void post(final Context context, String url, Map<String, Object> params, final HttpCallBack httpCallBack, final boolean cache) {
// 省略部分代码......
RequestBody requestBody = appendBody(params);
Request request = new Request.Builder()
.url(url)
.tag(context)
.post(requestBody)
.build();
mOkHttpClient.newCall(request).enqueue(
new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
executeError(httpCallBack, e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String resultJson = response.body().string();
executeSuccessMethod(httpCallBack, resultJson);
// 缓存处理,下一期我们没事干,自己手写数据库框架
}
}
);
}
/**
* 执行成功的方法
**/
private void executeSuccessMethod(final HttpCallBack httpCallBack, final String resultJson) {
try {
HttpUtils.handler.post(new Runnable() {
@Override
public void run() {
httpCallBack.onSucceed(resultJson);
}
});
} catch (Exception e) {
executeError(httpCallBack, e);
e.printStackTrace();
}
}
/**
* 执行失败的方法
*/
private void executeError(final HttpCallBack httpCallBack, final Exception e) {
HttpUtils.handler.post(new Runnable() {
@Override
public void run() {
httpCallBack.onError(e);
}
});
}
@Override
public void get(Context context, String url, Map<String, Object> params, final HttpCallBack httpCallBack, boolean cache) {
// 省略部分代码......
Request.Builder requestBuilder = new Request.Builder().url(url).tag(context);
Request request = requestBuilder.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
httpCallBack.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String resultJson = response.body().string();
// 当然有的时候还需要不同的些许处理
HttpUtils.handler.post(new Runnable() {
@Override
public void run() {
httpCallBack.onSucceed(result);
}
});
}
});
}
我们可以自己试试Retrofit的方式,这里我就不写了,毕竟很多人对于Retrofit并不是特别了解。自己也希望可以从RxJava开始写文章然后一步一步的上升到Retrofit。总之现在已经有了一个默认的OkHttpEngine了,如果需要配置或者切换我们需要去自定义一个引擎,然后切换到当前引擎就可以了,我们看一下怎么使用:
HttpUtils.with(context)
.exchangeEngine(new RetrofitEngine());// 切换成Retrofit引擎
.url(UrlConstant.CITY_MAIN_PAGE) // 路径
.addParam("city", mCurrentCity) // 添加参数
.cache(true) // 需要读缓存
.post() // post提交
.execute(new HttpCallBack<CityFragmentEntity>() {
@Override
public void onError(Exception e) {
// 错误回调
}
@Override
public void onSucceed(CityFragmentEntity result) {
// result 返回的解析好的对象 可以直接操作不需要再Json解析
// 成功的回调
}
});
这其实也没什么就是方便以后如果有了更好的第三方网络框架那么我们可以在Application中配置引擎,也可以每次请求的时候指定不同的引擎,这其实就是面向接口编程而已,这里还遗留了一个问题就是数据缓存,下一期我们需要利用面向对象的思想自己动手去写一套数据库封装,我们得按需定制把数据库写到外部存储卡中,还需要考虑数据库加密,Query懒加载,Lucene辅助搜索等等等等,不光是为了造轮子而是为了更好的了解其他数据库框架的原理。
所有分享大纲:2017Android进阶之路与你同行