原封装地址为鸿神的Android 一个改善的okHttp封装库。以下是自我总结和理解,不自己写一遍实在理解不了 - -!写完后扔掉又太可惜了,so.....
OkHttp的基本请求
创建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
构造RequestBody
RequestBody body = new ReuqestBody();
构造Request
Request request = new Request.Builder().url("").tag("").build();
创建Call对象,将Request加入Call对象中
Call call = client.newCall(request);
将Call对象加入调度,并提供回调函数
call.enqueue(new CallBack());
重点区别在于RequestBody创建方式的不同。我们希望对着5个步骤进行封装,
以上步骤基本封装完成,接下来分析细节实现。
OkHttpManager类
我们希望此类中可以进行总体的管理
希望对请求时间,超时时间等进行默认限制,所以定义字段DEFAULT_MILLISECONDS;
希望此类可以封装UI线程,这样可以避免编写大量的Hndaler通信,所以定义变量mDelivery实现主线程的UI通信;
同时封装变量mOkHttpClient,并封装OkHttpManager本身,采用单例模式提供getInstance方法获取实例;
我们在构造函数中进行mDelivery、mOkHttpClient变量的初始化工作。对应步骤1,代码如下:
private OkHttpManager(OkHttpClient okHttpClient) {
if (okHttpClient == null) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//builder.cookieJar(null);
//builder.hostnameVerifier(null);
mOkHttpClient = builder.build();
mDelivery = new Handler(Looper.getMainLooper());
} else {
mOkHttpClient = okHttpClient;
}
}
OkHttpRequest类
Request封装类,创建变量Request、RequestBody。
作为Request封装类,应该具有Request请求构造中的基本变量,所以我们创建tag(标记请求),params(保存参数),header(请求头信息),url(请求链接)四个基本参数;并创建Request.Builder对象用来构造请求。
构造函数
我们在构造函数中进行四个基本变量的初始化操作,并进行参数校验,进而使用builder对象去构造基本对象请求
对应步骤3 代码如下:
public OkHttpRequest(String url, Object tag, Map<String, String> params, Map<String, String> headers) {
this.mUrl = url;
this.mTag = tag;
this.params = params;
this.mHeaders = headers;
if (StringUtils.isNullOrEmpty(url)) {
Exception.illegalArgument("url 不能为空");
}
initBuilder();
}
/**
* 初始化Builder
*/
protected void initBuilder() {
builder.url(mUrl).tag(mTag);
appendHeaders();
}
/**
* 构建请求头
*/
protected void appendHeaders() {
Headers.Builder headerBuilder = new Headers.Builder();
if (mHeaders == null || mHeaders.isEmpty()) {
return;
}
builder.headers(headerBuilder.build());
for (String key : mHeaders.keySet()) {
headerBuilder.add(key, mHeaders.get(key));
}
}
每个请求的不同之处在于参数的构造情况,所以我们创建抽象方法buildRequestBody进行参数构造(对应步骤2),创建抽象方法buildRequest构造请求,buildRequest需传入RequestBody变量
创建方法generateRequest,在内部进行Request的构造,代码如下:
public Request generateRequest(CallBack callback) {
RequestBody requestBody = buildRequestBody();
RequestBody warpRequestBody = warpRequestBody(requestBody, callback);
Request request = buildRequest(warpRequestBody);
return request;
}
RequestCall类
对OkHttpRequest类的二次封装;因为是对OkHttpRequest类的封装,所以拥有变量mOkHttpRequest、mRequest和mCall;
创建方法generateRequest,通过OkHttpRequest.generateRequest拿到构造的Request
创建方法buildCall(对应步骤4),在此方法中构造Call,如果对超时、请求时间等有限制,则构造新的OkHttpClient,并将Call加入调度,对应步骤5
代码如下:
/**
* 构造Call对象
* @param callBack
* @return
*/
public Call buildCall(CallBack callBack) {
mRequest = generateRequest(callBack);
if (connTimeOut > 0 || writeTimeOut > 0 || readTimeOut > 0) {
connTimeOut = connTimeOut > 0 ? connTimeOut : OkHttpManager.DEFAULT_MILLISECONDS;
writeTimeOut = writeTimeOut > 0 ? connTimeOut : OkHttpManager.DEFAULT_MILLISECONDS;
readTimeOut = readTimeOut > 0 ? connTimeOut : OkHttpManager.DEFAULT_MILLISECONDS;
clone = OkHttpManager.getInstance().getOkHttpClient().newBuilder()
.connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)
.writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)
.readTimeout(readTimeOut, TimeUnit.MILLISECONDS)
.build();
mCall = clone.newCall(mRequest);
} else {
mCall = OkHttpManager.getInstance().getOkHttpClient().newCall(mRequest);
}
return mCall;
}
/**
* 获取Request
* @param callBack
* @return
*/
private Request generateRequest(CallBack callBack) {
return mOkHttpRequest.generateRequest(callBack);
}
提供excute方法进行调度方法,将调度的实现过程转移至OkHttpManager中
/**
* 调度方法
* @param callback
*/
public void excute(CallBack callback) {
buildCall(callback);
if (callback != null) {
callback.onBefore(mRequest);
}
OkHttpManager.getInstance().excute(this, callback);
}
最终,我们在OkHttpManager类中添加调度方法,传入二次封装类RequestCall、CallBack两个参数。并通过RequestCall获取Call对象,然后进行调度。代码如下:
/**
* 最终调度
* @param requestCall
* @param callback
*/
public void excute(final RequestCall requestCall, CallBack callback) {
if (callback == null) {
callback = CallBack.DEFAULT_CALLBACK;
}
final CallBack finalCallback = callback;
requestCall.getCall().enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFailResultCallback(call, e, finalCallback);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.code() >= 400 && response.code() <= 599) {
sendFailResultCallback(call, new RuntimeException(response.body().string()), finalCallback);
return;
}
Object o = finalCallback.parseNetworkResponse(response);
sendSuccessResultCallback(o, finalCallback);
}
});
}
/**
* 成功回调
* @param o
* @param finalCallback
*/
private void sendSuccessResultCallback(final Object o, final CallBack finalCallback) {
mDelivery.post(new Runnable() {
@Override
public void run() {
finalCallback.onSuccess(o);
finalCallback.onAfter();
}
});
}
/**
* 失败回调
* @param call
* @param e
* @param finalCallback
*/
private void sendFailResultCallback(final Call call, final Exception e, final CallBack finalCallback) {
mDelivery.post(new Runnable() {
@Override
public void run() {
finalCallback.onFailure(call, e);
finalCallback.onAfter();
}
});
}
以上,所有步骤均已实现完毕。
使用时,例如我们希望创建一个通用post请求,则先创建PostRequest继承OkHttpRequest。重写方法biuldResponseBody即可,代码如下:
@Override
public RequestBody warpRequestBody(RequestBody requestBody, final CallBack callback) {
if (callback == null) return requestBody;
CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody, new CountingRequestBody.Listener() {
@Override
public void onRequestProgress(final long bytesWritten, final long contentLength) {
OkHttpManager.getInstance().getDelivery().post(new Runnable() {
@Override
public void run() {
callback.inProcess(bytesWritten * 1.0f / contentLength);
}
});
}
});
return super.warpRequestBody(requestBody, callback);
}
@Override
protected Request buildRequest(RequestBody requestBody) {
return builder.post(requestBody).build();
}
@Override
protected RequestBody buildRequestBody() {
FormBody.Builder builder = new FormBody.Builder();
addParams(builder);
return builder.build();
}
在OkHttpManager类中添加方法post(url,tag...)等,返回RequestCall。
接下来,我们希望通过post.url(url)的方式进行参数构建,有利代码可读性。
首先,创建抽象OkHttpRequestBuilder类,类中增加抽象方法url、tag、header,参数的不确定性,提供hasParams接口进行参数绑定。最终提供build方法返回一个RequestCall对象进行最终调度。
所以在OkHttpManager类添加方法post,返回一个PostRequestBuilder类,重写build方法,将url等变量传递至PostRequest构造函数中,返回RequestCall对象。代码如下:
@Override
public RequestCall build() {
return new PostFormRequest(url, tag, params, header).build();
}
最终的调用形式便成为
OkHttpManager. post() //获取RequestBilder抽象类
.addParams("username", "测试新框架") //设置参数
.addParams("password", "123456") //设置参数
.url(UrlConfig.REGISTER) //设置参数
.tag(this) //设置参数
.build()
.excute(new CallBack<String>() { //调用RequestCall.excute方法,并传入回调函数
@Override
public String parseNetworkResponse(Response response) {
try {
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void onSuccess(String response) {
ToastUtils.show(getActivity(), response, 1000);
}
@Override
public void onFailure(Call call, Exception e) {
}
});
完毕,以上是个人对封装的理解,有错误的地方请指出,原封装地址为鸿神的Android 一个改善的okHttp封装库。