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

须知少年凌云志,曾许人间第一流。这篇文章主要讲述Android实际开发之网络请求组件的封装(OkHttp为核心)相关的知识,希望能为你提供帮助。
趁周末时间撸了两天代码,将OkHttp网络请求框架进行了一次简单封装,对于实际开发非常有用。。此次封装主要针对我们经常使用的网络请求的步骤进行封装,在已有框架OkHttp的基础上进行实际开发的封装发送一个网络请求,有以下三个功能模块:一:request处理,其中包含的模块有请求参数的封装,url的传入,创建好get/post的请求对象(正如思维导图上所展示的request的处理)二:OkHttp核心处理,把OkHttp核心的一些请求参数进行设置,https的支持,根据我们实际开发的环境进行一些静态参数设置三:callback处理,其中包含的有回调数据的处理,异常处理,将网络请求结果等信息转发到UI线程,以及实际开发中遇到很多的json转化对应的实体趁周末时间撸了两天代码,将OkHttp网络请求框架进行了一次简单封装,对于实际开发非常有用。。
 
【Android实际开发之网络请求组件的封装(OkHttp为核心)】此次封装主要针对我们经常使用的网络请求的步骤进行封装,在已有框架OkHttp的基础上进行实际开发的封装
发送一个网络请求,有以下三个功能模块:
一:request处理
二:OkHttp核心处理
三:callback处理
我们进行网络请求组件的封装也是根据这三大模块进行封装的,下面规划一下这次封装的一个思维导图:

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

文章图片

 
根据以上思维导图,我们第一步,先进行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* * 文件作者:ouyangshengduo 11* * 创建时间:2017/3/25 12* * 文件描述:接收请求参数,为我们生成request对象 13* * 修改历史:2017/3/25 21:02************************************* 14**/ 15 16 public class CommonRequest { 17 18/** 19* 20* @param url 21* @param params 22* @return返回一个创建好的Request对象 23*/ 24public static Request createPostRequest(String url, RequestParams params){ 25 26FormBody.Builder mFormBodyBuild = new FormBody.Builder(); 27 28if(params != null){ 29for(Map.Entry< String,String> entry: params.urlParams.entrySet()){ 30//将请求参数遍历添加到我们的请求构件类中 31mFormBodyBuild.add(entry.getKey(),entry.getValue()); 32} 33} 34//通过请求构件类的build方法获取到真正的请求体对象 35FormBody mFormBody = mFormBodyBuild.build(); 36return new Request.Builder().url(url).post(mFormBody).build(); 37} 38 39/** 40* 41* @param url 42* @param params 43* @return 通过传入的参数,返回一个创建Get类型的Request对象 44*/ 45public static Request createGetRequest(String url,RequestParams params){ 46 47StringBuilder urlBuilder = new StringBuilder(url).append("?"); 48if(params != null){ 49for(Map.Entry< String,String> entry: params.urlParams.entrySet()){ 50//将请求参数遍历添加到我们的请求构件类中 51urlBuilder.append(entry.getKey()).append("="). 52append(entry.getValue()).append("& "); 53} 54} 55 56return new Request.Builder().url(urlBuilder.substring(0,urlBuilder.length() - 1)) 57.get().build(); 58} 59 60 }

 
其中的RequestParams功能比较简单,是封装所有的请求参数到HashMap中,可展开查看代码内容:
Android实际开发之网络请求组件的封装(OkHttp为核心)

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

文章图片
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 keythe 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 keythe 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* * 文件作者:ouyangshengduo 18* * 创建时间:2017/3/25 19* * 文件描述:请求的发送,请求参数的配置,https的支持 20* * 修改历史:2017/3/25 21:21************************************* 21**/ 22 23 public class CommonOkHttpClient { 24 25private static final int TIME_OUT = 30; //超时参数 26private static OkHttpClient mOkHttpClient; 27 28//为我们的client去配置参数 29static{ 30 31//创建我们client对象的构建者 32OkHttpClient.Builder okHttpBuilder = new OkHttpClient().newBuilder(); 33//为构建者填充超时时间 34okHttpBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS); 35okHttpBuilder.readTimeout(TIME_OUT,TimeUnit.SECONDS); 36okHttpBuilder.writeTimeout(TIME_OUT,TimeUnit.SECONDS); 37 38//确保支持重定向 39okHttpBuilder.followRedirects(true); 40 41//https支持 42okHttpBuilder.hostnameVerifier(new HostnameVerifier() { 43@Override 44public boolean verify(String hostname, SSLSession session) { 45return true; 46} 47}); 48okHttpBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory()); 49//生成我们client对象 50mOkHttpClient = okHttpBuilder.build(); 51} 52 53 54/** 55* 56* @param request 57* @param commonCallback 58* @return返回Call实例 59*/ 60public static Call sendRequest(Request request, CommonJsonCallback commonCallback){ 61 62Call call = mOkHttpClient.newCall(request); 63call.enqueue(commonCallback); 64return 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 responseObj 16*/ 17public void onSuccess(Object responseObj); 18 19/** 20* 请求失败回调事件处理 21* @param responseObj 22*/ 23public 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 13public DisposeDataListener mListener; 14public Class< ?> mClass = null; //字节码 15 16/** 17* 数据原封不动 18* @param listener 19*/ 20public DisposeDataHandle(DisposeDataListener listener){ 21this.mListener = listener; 22} 23 24/** 25* json对象到实体对象的转化 26* @param listener 27* @param clazz 28*/ 29public DisposeDataHandle(DisposeDataListener listener,Class< ?> clazz){ 30this.mListener = listener; 31this.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//与服务器返回的字段的一个对应关系 30protectedfinal String RESULT_CODE = "ecode"; //有返回则对于http请求来说是成功的 31protectedfinal int RESULT_CODE_VALUE = https://www.songbingjia.com/android/0; 32protectedfinal String ERROR_MSG ="emsg"; 33protectedfinal String EMPTY_MSG = ""; 34 35/** 36* 自定义了一些我们常见的一些异常类型 37*/ 38protected final int NETWORK_ERROR = -1; //网络错误 39protected final int JSON_ERROR = -2; //json解析错误 40protected final int OTHER_ERROR = -3; //其他错误 41 42private Class< ?> mClass; 43private Handler mDeliveryHandler; //进行消息的转发,将子线程的数据转发到UI线程 44private DisposeDataListener mListener; 45 46public CommonJsonCallback(DisposeDataHandle handle){ 47this.mClass = handle.mClass; 48this.mListener = handle.mListener; 49this.mDeliveryHandler = new Handler(Looper.getMainLooper()); 50} 51 52//请求失败处理 53@Override 54public void onFailure(final Call call,final IOException e) { 55 56mDeliveryHandler.post(new Runnable() { 57@Override 58public void run() { 59 60mListener.onFailure(new OkHttpException(NETWORK_ERROR,e)); 61} 62}); 63} 64 65@Override 66public void onResponse(Call call, Response response) throws IOException { 67 68final String result = response.body().toString(); 69mDeliveryHandler.post(new Runnable() { 70@Override 71public void run() { 72handleResponse(result); 73} 74}); 75} 76 77/** 78* 处理服务器返回的数据 79* @param responseObj 80*/ 81private void handleResponse(Object responseObj){ 82 83//为了保证代码的健壮性 84if(responseObj == null & & responseObj.toString().trim().equals("")){ 85 86mListener.onFailure(new OkHttpException(NETWORK_ERROR,EMPTY_MSG)); 87return; 88} 89 90try{ 91JSONObject result = new JSONObject(responseObj.toString()); 92//开始尝试解析json 93if(result.has(RESULT_CODE)){ 94 95//从json对象中取出我们的响应码,若为0(与服务器一致),则是正常的响应 96if(result.getInt(RESULT_CODE) == RESULT_CODE_VALUE){ 97 98if(mClass == null){ 99mListener.onSuccess(responseObj); 100}else{ 101//即,需要我们将json对象转化为实体对象 102Gson gson = new Gson(); 103Object obj = gson.fromJson(responseObj.toString(),mClass); 104//标明正确的转化为了实体对象 105if(obj != null){ 106mListener.onSuccess(obj); 107}else{ 108//返回的不是合法的json 109mListener.onFailure(new OkHttpException(JSON_ERROR,EMPTY_MSG)); 110} 111} 112}else{ 113//将服务器返回给我们的异常回调到应用层去处理 114mListener.onFailure(new OkHttpException(OTHER_ERROR,result.get(RESULT_CODE))); 115} 116} 117 118}catch(Exception e){ 119mListener.onFailure(new OkHttpException(OTHER_ERROR,e.getMessage())); 120} 121 122} 123 }

 
以上就是对于response的一个封装,其中包含的有回调数据的处理,异常处理,将网络请求结果等信息转发到UI线程,以及实际开发中遇到很多的json转化对应的实体
根据思维导图里面的描述,已经将request层,OkHttp核心层,response层都进行了封装,对于实际开发中用到的网络请求,我们已经形成了自己的网络请求组件,对于
我们项目的业务层与OkHttp核心进行了解耦,对于实际项目的开发以及维护都相当有作用。
到此,网络请求组件的封装已经初步完成,对于一些第三方框架的封装有了一些感悟,感谢慕课网的老师的讲解,也感谢不断学习的自己。
项目源码:源码地址

    推荐阅读