您的位置:首页 > 理论基础 > 计算机网络

Android实际开发之网络请求组件的封装(OkHttp为核心)

2017-03-26 22:35 851 查看
趁周末时间撸了两天代码,将OkHttp网络请求框架进行了一次简单封装,对于实际开发非常有用。。

此次封装主要针对我们经常使用的网络请求的步骤进行封装,在已有框架OkHttp的基础上进行实际开发的封装

发送一个网络请求,有以下三个功能模块:

一:request处理

二:OkHttp核心处理

三:callback处理

我们进行网络请求组件的封装也是根据这三大模块进行封装的,下面规划一下这次封装的一个思维导图:

package com.oysd.okhttp.request;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* *****************************************************************
* * 文件作者:ouyangshengduo
* * 创建时间:2017/3/25
* * 文件描述:封装所有的请求参数到HashMap中
* * 修改历史:2017/3/25 16:36*************************************
**/

public class RequestParams {

public ConcurrentHashMap<String,String> urlParams = new ConcurrentHashMap<String,String>();
public ConcurrentHashMap<String,Object> fileParams = new ConcurrentHashMap<String,Object>();

/**
* Constructs a new empty {@code RequestParams} instance.
*/
public RequestParams() {
this((Map<String, String>) null);
}

/**
* Constructs a new RequestParams instance containing the key/value string
* params from the specified map.
*
* @param source the source key/value string map to add.
*/
public RequestParams(Map<String, String> source) {
if (source != null) {
for (Map.Entry<String, String> entry : source.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
}

/**
* Constructs a new RequestParams instance and populate it with a single
* initial key/value string param.
*
* @param key   the key name for the intial param.
* @param value the value string for the initial param.
*/
public RequestParams(final String key, final String value) {
this(new HashMap<String, String>() {
{
put(key, value);
}
});
}

/**
* Adds a key/value string pair to the request.
*
* @param key   the key name for the new param.
* @param value the value string for the new param.
*/
public void put(String key, String value) {
if (key != null && value != null) {
urlParams.put(key, value);
}
}

public void put(String key, Object object) throws FileNotFoundException {

if (key != null) {
fileParams.put(key, object);
}
}

public boolean hasParams() {
if(urlParams.size() > 0 || fileParams.size() > 0){

return true;
}
return false;
}

}


View Code

以上,我们的就把request的功能处理封装好了,其中包含的模块有请求参数的封装,url的传入,创建好get/post的请求对象(正如思维导图上所展示的request的处理)

第二步,对OkHttp核心进行封装,下面我们新建类CommonOkHttpClient,并实现OkHttp核心的发送get/post请求,请求相关参数的设置,以及https的支持:

package com.oysd.okhttp;

import com.oysd.okhttp.https.HttpsUtils;
import com.oysd.okhttp.response.CommonJsonCallback;

import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;

/**
* *****************************************************************
* * 文件作者:ouyangshengduo
* * 创建时间:2017/3/25
* * 文件描述:请求的发送,请求参数的配置,https的支持
* * 修改历史:2017/3/25 21:21*************************************
**/

public class CommonOkHttpClient {

private static final int TIME_OUT = 30;//超时参数
private static OkHttpClient mOkHttpClient;

//为我们的client去配置参数
static{

//创建我们client对象的构建者
OkHttpClient.Builder okHttpBuilder = new OkHttpClient().newBuilder();
//为构建者填充超时时间
okHttpBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpBuilder.readTimeout(TIME_OUT,TimeUnit.SECONDS);
okHttpBuilder.writeTimeout(TIME_OUT,TimeUnit.SECONDS);

//确保支持重定向
okHttpBuilder.followRedirects(true);

//https支持
okHttpBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
okHttpBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());
//生成我们client对象
mOkHttpClient = okHttpBuilder.build();
}

/**
*
* @param request
* @param commonCallback
* @return返回Call实例
*/
public static Call sendRequest(Request request, CommonJsonCallback commonCallback){

Call call = mOkHttpClient.newCall(request);
call.enqueue(commonCallback);
return call;
}

}


以上就是把OkHttp核心的一些请求参数进行设置,根据我们实际开发的环境进行一些静态参数设置,

在这里说明一下,对于一些公用的一些组件,正确使用static并不会造成内存泄露,要知道Android源码里面,很多都用到了static,所以可以放心。。

第三步,就是对于我们OkHttp核心的回调进行封装了

新建类DisposeDataListener作为我们的自定义事件监听,和OkHttp的onSucess和onFailure类似,但这个事件监听是属于我们项目自己的,

万一哪天OkHttp的开发团队将这两个事件改名字了或者不用了,我们自己的项目中的业务层至少不会产生任何影响

package com.oysd.okhttp.listener;

/**
* *****************************************************************
* * 文件作者:ouyangshengduo
* * 创建时间:2017/3/26
* * 文件描述:自定义事件监听
* * 修改历史:2017/3/26 10:22*************************************
**/

public interface DisposeDataListener {

/**
* 请求成功回调事件处理
* @param responseObj
*/
public void onSuccess(Object responseObj);

/**
* 请求失败回调事件处理
* @param responseObj
*/
public void onFailure(Object responseObj);
}


然后新建一个DisposeDataHandle类,作为我们实际开发中用的最多的json数据的一个json对象到实体对象的一个转化

package com.oysd.okhttp.listener;

/**
* *****************************************************************
* * 文件作者:ouyangshengduo
* * 创建时间:2017/3/26
* * 文件描述:json对象到实体对象的一个讲话
* * 修改历史:2017/3/26 10:42*************************************
**/

public class DisposeDataHandle {

public DisposeDataListener mListener;
public Class<?> mClass = null;//字节码

/**
* 数据原封不动
* @param listener
*/
public DisposeDataHandle(DisposeDataListener listener){
this.mListener = listener;
}

/**
* json对象到实体对象的转化
* @param listener
* @param clazz
*/
public DisposeDataHandle(DisposeDataListener listener,Class<?> clazz){
this.mListener = listener;
this.mClass = clazz;
}
}


以上是作为回调内容一些处理功能,对于response的封装,主要功能在CommonJsonCallback(以实际开发中遇到最多的json格式的处理为例):

package com.oysd.okhttp.response;

import android.os.Handler;
import android.os.Looper;

import com.google.gson.Gson;
import com.oysd.okhttp.exception.OkHttpException;
import com.oysd.okhttp.listener.DisposeDataHandle;
import com.oysd.okhttp.listener.DisposeDataListener;

import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

/**
* *****************************************************************
* * 文件作者:ouyangshengduo
* * 创建时间:2017/3/26
* * 文件描述:专门处理JSON的回调响应
* * 修改历史:2017/3/26 10:53*************************************
**/

public class CommonJsonCallback implements Callback{

//与服务器返回的字段的一个对应关系
protected  final String RESULT_CODE = "ecode";//有返回则对于http请求来说是成功的
protected  final int RESULT_CODE_VALUE = 0;
protected  final String ERROR_MSG = "emsg";
protected  final String EMPTY_MSG = "";

/**
* 自定义了一些我们常见的一些异常类型
*/
protected final int NETWORK_ERROR = -1;//网络错误
protected final int JSON_ERROR = -2;//json解析错误
protected final int OTHER_ERROR = -3;//其他错误

private Class<?> mClass;
private Handler mDeliveryHandler;//进行消息的转发,将子线程的数据转发到UI线程
private DisposeDataListener mListener;

public CommonJsonCallback(DisposeDataHandle handle){
this.mClass = handle.mClass;
this.mListener = handle.mListener;
this.mDeliveryHandler = new Handler(Looper.getMainLooper());
}

//请求失败处理
@Override
public void onFailure(final Call call,final IOException e) {

mDeliveryHandler.post(new Runnable() {
@Override
public void run() {

mListener.onFailure(new OkHttpException(NETWORK_ERROR,e));
}
});
}

@Override
public void onResponse(Call call, Response response) throws IOException {

final String result = response.body().toString();
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
handleResponse(result);
}
});
}

/**
* 处理服务器返回的数据
* @param responseObj
*/
private void handleResponse(Object responseObj){

//为了保证代码的健壮性
if(responseObj == null && responseObj.toString().trim().equals("")){

mListener.onFailure(new OkHttpException(NETWORK_ERROR,EMPTY_MSG));
return;
}

try{
JSONObject result = new JSONObject(responseObj.toString());
//开始尝试解析json
if(result.has(RESULT_CODE)){

//从json对象中取出我们的响应码,若为0(与服务器一致),则是正常的响应
if(result.getInt(RESULT_CODE) == RESULT_CODE_VALUE){

if(mClass == null){
mListener.onSuccess(responseObj);
}else{
//即,需要我们将json对象转化为实体对象
Gson gson = new Gson();
Object obj = gson.fromJson(responseObj.toString(),mClass);
//标明正确的转化为了实体对象
if(obj != null){
mListener.onSuccess(obj);
}else{
//返回的不是合法的json
mListener.onFailure(new OkHttpException(JSON_ERROR,EMPTY_MSG));
}
}
}else{
//将服务器返回给我们的异常回调到应用层去处理
mListener.onFailure(new OkHttpException(OTHER_ERROR,result.get(RESULT_CODE)));
}
}

}catch(Exception e){
mListener.onFailure(new OkHttpException(OTHER_ERROR,e.getMessage()));
}

}
}


以上就是对于response的一个封装,其中包含的有回调数据的处理,异常处理,将网络请求结果等信息转发到UI线程,以及实际开发中遇到很多的json转化对应的实体

根据思维导图里面的描述,已经将request层,OkHttp核心层,response层都进行了封装,对于实际开发中用到的网络请求,我们已经形成了自己的网络请求组件,对于

我们项目的业务层与OkHttp核心进行了解耦,对于实际项目的开发以及维护都相当有作用。

到此,网络请求组件的封装已经初步完成,对于一些第三方框架的封装有了一些感悟,感谢慕课网的老师的讲解,也感谢不断学习的自己。

项目源码:源码地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: