主要是记录一下封装的思路~
封装的好处:
1.可复用性
2.与业务逻辑隔离
3.可扩展性
封装的思路:
封装一个公共的OkHttpClient
封装一个通用的请求创建类CommonRequest
封装一个通用的响应解析类CommonResponse
封装过程
1响应解析类的封装(以json数据为例)
- 自定义异常类,返回errorCode和errorMsg到业务层
public class OkHttpException extends Exception {
/** * 服务端返回的错误码 */
private int errorCode;
/** * 服务端返回的错误信息 */
private Object errorMsg;
public OkHttpException(int errorCode, Object errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public int getErrorCode() {
return errorCode;
}
public Object getErrorMsg() {
return errorMsg;
}
}
- 自定义listener,真正处理业务逻辑的地方
public interface ResponseDataListener {
/** * 请求成功回调事件处理
* @param responseObj
*/
void onSuccess(Object responseObj);
/** * 请求失败回调时间处理
* @param reasonObj
*/
void onFailure(Object reasonObj);
}
为什么不直接使用OkHttp的Callback,而是额外自定义一个listener?
之所以这样做,是为了将业务逻辑和通用的网络处理完全分开, 统一的网络处理可以统一放在Callback中处理, 然后再调用自定义的listener对业务逻辑进行处理。 另外一个重要原因是:Callback的onFailure只针对网络请求的异常情况, 而实际开发中,我们不仅要关注网络异常,还要关注业务逻辑异常, 通过自定义listener可以做到一点,因为callback的接口由框架自身调用, 而listener的接口我们可以自由调用。
- ResponseDataHandle
public class ResponseDataHandle {
public ResponseDataListener mListener = null;//自定义的ResponseDataListener
public Class mClass = null;//json数据对应的实体类
public ResponseDataHandle(ResponseDataListener listener) {
this.mListener = listener;
}
public ResponseDataHandle(ResponseDataListener listener, Class clazz){
this.mListener = listener;
this.mClass = clazz;
}
}
- 对callback的封装
重写onFailure(),onResponse(),调用自定义listener的onSuccess()和onFailure()进行逻辑处理,注意切换到主线程操作。
public class CommonJsonCallBackimplements Callback {
protected final StringRESULT_CODE ="errorCode";
protected final int RESULT_CODE_VALUE =0;
protected final StringERROR_MSG ="errorMsg";
protected final StringEMPTY_MSG ="";
protected final int NETWORK_ERROR = -1;
protected final int JSON_ERROR = -2;
protected final int OTHER_ERROR = -3;
/**
* 将其他线程的数据转发到UI线程
*/
private HandlermDeliveryHandler;
private ResponseDataListenermListener;
private ClassmClass;
public CommonJsonCallBack(ResponseDataHandle handle) {
this.mListener = handle.mListener;
this.mClass = handle.mClass;
this.mDeliveryHandler =new Handler(Looper.getMainLooper());
}
@Override
public void onFailure(Call call, final IOException e) {
//此时还在非UI线程,需要转发到主线程
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, e.getMessage()));
}
});
}
@Override
public void onResponse(Call call, Response response)throws IOException {
final String result = response.body().string();
// response.headers();todo 处理cookie
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
handleResponse(result);
}
});
}
private void handleResponse(Object responseObj) {
if (responseObj ==null) {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG));
return;
}
try {
JSONObject result =new JSONObject(responseObj.toString());
if (result.has(RESULT_CODE)) {
if (result.optInt(RESULT_CODE) ==RESULT_CODE_VALUE) {
if (mClass ==null) {
mListener.onSuccess(result);
}else {
Object obj = JSON.parseObject(responseObj.toString(), mClass);
if (obj !=null) {
mListener.onSuccess(obj);
}else {
mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG));
}
}
}else {
if (result.has(ERROR_MSG)) {
mListener.onFailure(new OkHttpException(result.optInt(RESULT_CODE), result.optString(ERROR_MSG)));
}else {
mListener.onFailure(new OkHttpException(result.optInt(RESULT_CODE), EMPTY_MSG));
}
}
}else {
if (result.has(ERROR_MSG)) {
mListener.onFailure(new OkHttpException(OTHER_ERROR, result.optString(ERROR_MSG)));
}
}
}catch (JSONException e) {
mListener.onFailure(new OkHttpException(JSON_ERROR, e.getMessage()));
}
}
}
2请求创建类的封装
- 对请求参数的封装
参数通常以键值对的形式存在,所以可以使用ConcurrentHashMap
public class RequestParams {
public ConcurrentHashMap urlParams =new ConcurrentHashMap<>();
public RequestParams() {
this(null);
}
public RequestParams(final String key, final String value) {
put(key, value);
}
public RequestParams(Map source) {
if (source !=null) {
for (Map.Entry entry : source.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
}
public void put(String key, String value) {
if (key !=null && value !=null) {
urlParams.put(key, value);
}
}
}
- 对request进行封装,提供get、post两个方法
public class CommonRequest {
public static RequestcreateGetRequest(String url, RequestParams params) {
StringBuilder urlBuilder =new StringBuilder(url).append("?");
if (params !=null) {
for (Map.Entry entry : params.urlParams.entrySet()) {
urlBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
return new Request.Builder().url(urlBuilder.substring(0, urlBuilder.length() -1)).get().build();
}
public static RequestcreatePostRequest(String url, RequestParams params) {
FormBody.Builder formBodyBuilder =new FormBody.Builder();
if (params !=null) {
for (Map.Entry entry : params.urlParams.entrySet()) {
formBodyBuilder.add(entry.getKey(), entry.getValue());
}
}
FormBody formBody = formBodyBuilder.build();
return new Request.Builder().url(url).post(formBody).build();
}
}
3Client的封装,包括设置一些请求的共用参数
public class CommonOkHttpClient {
private static final int TIME_OUT =30;
private static OkHttpClientsOkHttpClient;
static {
OkHttpClient.Builder okHttpClientBuilder =new OkHttpClient.Builder();
okHttpClientBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
okHttpClientBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.followSslRedirects(true);
okHttpClientBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());
sOkHttpClient = okHttpClientBuilder.build();
}
public static Callget(Request request, ResponseDataHandle handle) {
Call call =sOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallBack(handle));
return call;
}
public static Callpost(Request request, ResponseDataHandle handle) {
Call call =sOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallBack(handle));
return call;
}
}
简单封装结束~
以一个get请求为例,直接使用的方式如下:
final Request request =new Request.Builder().url("https://www.baidu.com").build();
OkHttpClient okHttpClient =new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response)throws IOException {
}
});
封装后的用法:
CommonOkHttpClient.get(CommonRequest.createGetRequest("https://www.baidu.com", null),
new ResponseDataHandle(new ResponseDataListener() {
@Override
public void onSuccess(Object responseObj) {
}
@Override
public void onFailure(Object reasonObj) {
}
}));
资源:慕课网