首页 > 代码库 > Android实际开发之网络请求组件的封装(OkHttp为核心)

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

趁周末时间撸了两天代码,将OkHttp网络请求框架进行了一次简单封装,对于实际开发非常有用。。

 

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

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

一:request处理

二:OkHttp核心处理

三:callback处理

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

技术分享

 

根据以上思维导图,我们第一步,先进行request的封装:

以下是封装的一个CommonRequest类:

 1 package com.oysd.okhttp.request; 2  3 import java.util.Map; 4  5 import okhttp3.FormBody; 6 import okhttp3.Request; 7  8 /** 9  * *****************************************************************10  * * 文件作者:ouyangshengduo11  * * 创建时间:2017/3/2512  * * 文件描述:接收请求参数,为我们生成request对象13  * * 修改历史:2017/3/25 21:02*************************************14  **/15 16 public class CommonRequest {17 18     /**19      *20      * @param url21      * @param params22      * @return返回一个创建好的Request对象23      */24     public static Request createPostRequest(String url, RequestParams params){25 26         FormBody.Builder mFormBodyBuild = new FormBody.Builder();27 28         if(params != null){29             for(Map.Entry<String,String> entry: params.urlParams.entrySet()){30                 //将请求参数遍历添加到我们的请求构件类中31                 mFormBodyBuild.add(entry.getKey(),entry.getValue());32             }33         }34         //通过请求构件类的build方法获取到真正的请求体对象35         FormBody mFormBody = mFormBodyBuild.build();36         return new Request.Builder().url(url).post(mFormBody).build();37     }38 39     /**40      *41      * @param url42      * @param params43      * @return 通过传入的参数,返回一个创建Get类型的Request对象44      */45     public static Request createGetRequest(String url,RequestParams params){46 47         StringBuilder urlBuilder = new StringBuilder(url).append("?");48         if(params != null){49             for(Map.Entry<String,String> entry: params.urlParams.entrySet()){50                 //将请求参数遍历添加到我们的请求构件类中51                 urlBuilder.append(entry.getKey()).append("=").52                         append(entry.getValue()).append("&");53             }54         }55 56         return new Request.Builder().url(urlBuilder.substring(0,urlBuilder.length() - 1))57                 .get().build();58     }59 60 }

 

其中的RequestParams功能比较简单,是封装所有的请求参数到HashMap中,可展开查看代码内容:

技术分享
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的支持:

 1 package com.oysd.okhttp; 2  3 import com.oysd.okhttp.https.HttpsUtils; 4 import com.oysd.okhttp.response.CommonJsonCallback; 5  6 import java.util.concurrent.TimeUnit; 7  8 import javax.net.ssl.HostnameVerifier; 9 import javax.net.ssl.SSLSession;10 11 import okhttp3.Call;12 import okhttp3.OkHttpClient;13 import okhttp3.Request;14 15 /**16  * *****************************************************************17  * * 文件作者:ouyangshengduo18  * * 创建时间:2017/3/2519  * * 文件描述:请求的发送,请求参数的配置,https的支持20  * * 修改历史:2017/3/25 21:21*************************************21  **/22 23 public class CommonOkHttpClient {24 25     private static final int TIME_OUT = 30;//超时参数26     private static OkHttpClient mOkHttpClient;27 28     //为我们的client去配置参数29     static{30 31         //创建我们client对象的构建者32         OkHttpClient.Builder okHttpBuilder = new OkHttpClient().newBuilder();33         //为构建者填充超时时间34         okHttpBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);35         okHttpBuilder.readTimeout(TIME_OUT,TimeUnit.SECONDS);36         okHttpBuilder.writeTimeout(TIME_OUT,TimeUnit.SECONDS);37 38         //确保支持重定向39         okHttpBuilder.followRedirects(true);40 41         //https支持42         okHttpBuilder.hostnameVerifier(new HostnameVerifier() {43             @Override44             public boolean verify(String hostname, SSLSession session) {45                 return true;46             }47         });48         okHttpBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());49         //生成我们client对象50         mOkHttpClient = okHttpBuilder.build();51     }52 53 54     /**55      *56      * @param request57      * @param commonCallback58      * @return返回Call实例59      */60     public static Call sendRequest(Request request, CommonJsonCallback commonCallback){61 62         Call call = mOkHttpClient.newCall(request);63         call.enqueue(commonCallback);64         return call;65     }66 67 68 }

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

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

 

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

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

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

 1 package com.oysd.okhttp.listener; 2  3 /** 4  * ***************************************************************** 5  * * 文件作者:ouyangshengduo 6  * * 创建时间:2017/3/26 7  * * 文件描述:自定义事件监听 8  * * 修改历史:2017/3/26 10:22************************************* 9  **/10 11 public interface DisposeDataListener {12 13     /**14      * 请求成功回调事件处理15      * @param responseObj16      */17     public void onSuccess(Object responseObj);18 19     /**20      * 请求失败回调事件处理21      * @param responseObj22      */23     public void onFailure(Object responseObj);24 }

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

 1 package com.oysd.okhttp.listener; 2  3 /** 4  * ***************************************************************** 5  * * 文件作者:ouyangshengduo 6  * * 创建时间:2017/3/26 7  * * 文件描述:json对象到实体对象的一个讲话 8  * * 修改历史:2017/3/26 10:42************************************* 9  **/10 11 public class DisposeDataHandle {12 13     public DisposeDataListener mListener;14     public Class<?> mClass = null;//字节码15 16     /**17      * 数据原封不动18      * @param listener19      */20     public DisposeDataHandle(DisposeDataListener listener){21         this.mListener = listener;22     }23 24     /**25      * json对象到实体对象的转化26      * @param listener27      * @param clazz28      */29     public DisposeDataHandle(DisposeDataListener listener,Class<?> clazz){30         this.mListener = listener;31         this.mClass = clazz;32     }33 }

 

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

  1 package com.oysd.okhttp.response;  2   3 import android.os.Handler;  4 import android.os.Looper;  5   6 import com.google.gson.Gson;  7 import com.oysd.okhttp.exception.OkHttpException;  8 import com.oysd.okhttp.listener.DisposeDataHandle;  9 import com.oysd.okhttp.listener.DisposeDataListener; 10  11 import org.json.JSONObject; 12  13 import java.io.IOException; 14  15 import okhttp3.Call; 16 import okhttp3.Callback; 17 import okhttp3.Response; 18  19 /** 20  * ***************************************************************** 21  * * 文件作者:ouyangshengduo 22  * * 创建时间:2017/3/26 23  * * 文件描述:专门处理JSON的回调响应 24  * * 修改历史:2017/3/26 10:53************************************* 25  **/ 26  27 public class CommonJsonCallback implements Callback{ 28  29     //与服务器返回的字段的一个对应关系 30     protected  final String RESULT_CODE = "ecode";//有返回则对于http请求来说是成功的 31     protected  final int RESULT_CODE_VALUE = http://www.mamicode.com/0; 32     protected  final String ERROR_MSG = "emsg"; 33     protected  final String EMPTY_MSG = ""; 34  35     /** 36      * 自定义了一些我们常见的一些异常类型 37      */ 38     protected final int NETWORK_ERROR = -1;//网络错误 39     protected final int JSON_ERROR = -2;//json解析错误 40     protected final int OTHER_ERROR = -3;//其他错误 41  42     private Class<?> mClass; 43     private Handler mDeliveryHandler;//进行消息的转发,将子线程的数据转发到UI线程 44     private DisposeDataListener mListener; 45  46     public CommonJsonCallback(DisposeDataHandle handle){ 47         this.mClass = handle.mClass; 48         this.mListener = handle.mListener; 49         this.mDeliveryHandler = new Handler(Looper.getMainLooper()); 50     } 51  52     //请求失败处理 53     @Override 54     public void onFailure(final Call call,final IOException e) { 55  56         mDeliveryHandler.post(new Runnable() { 57             @Override 58             public void run() { 59  60                 mListener.onFailure(new OkHttpException(NETWORK_ERROR,e)); 61             } 62         }); 63     } 64  65     @Override 66     public void onResponse(Call call, Response response) throws IOException { 67  68         final String result = response.body().toString(); 69         mDeliveryHandler.post(new Runnable() { 70             @Override 71             public void run() { 72                 handleResponse(result); 73             } 74         }); 75     } 76  77     /** 78      * 处理服务器返回的数据 79      * @param responseObj 80      */ 81     private void handleResponse(Object responseObj){ 82  83         //为了保证代码的健壮性 84         if(responseObj == null && responseObj.toString().trim().equals("")){ 85  86             mListener.onFailure(new OkHttpException(NETWORK_ERROR,EMPTY_MSG)); 87             return; 88         } 89  90         try{ 91             JSONObject result = new JSONObject(responseObj.toString()); 92             //开始尝试解析json 93             if(result.has(RESULT_CODE)){ 94  95                 //从json对象中取出我们的响应码,若为0(与服务器一致),则是正常的响应 96                 if(result.getInt(RESULT_CODE) == RESULT_CODE_VALUE){ 97  98                     if(mClass == null){ 99                         mListener.onSuccess(responseObj);100                     }else{101                         //即,需要我们将json对象转化为实体对象102                         Gson gson = new Gson();103                         Object obj = gson.fromJson(responseObj.toString(),mClass);104                         //标明正确的转化为了实体对象105                         if(obj != null){106                             mListener.onSuccess(obj);107                         }else{108                             //返回的不是合法的json109                             mListener.onFailure(new OkHttpException(JSON_ERROR,EMPTY_MSG));110                         }111                     }112                 }else{113                     //将服务器返回给我们的异常回调到应用层去处理114                     mListener.onFailure(new OkHttpException(OTHER_ERROR,result.get(RESULT_CODE)));115                 }116             }117 118         }catch(Exception e){119             mListener.onFailure(new OkHttpException(OTHER_ERROR,e.getMessage()));120         }121 122     }123 }

 

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

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

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

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

项目源码:源码地址

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