首页 > 代码库 > 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; }}
以上,我们的就把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为核心)