OKhttp网络请求组件的封装



    以OKhttp为例,对网络请求组件进行封装。  如果我们不封装组件的话也可以使用,但是每次调用都需要重写方法,就会产生大量代码,并且全部暴露在activity中,不利于后  续的管理。所以封装是必不可少的。


接下来分析就分析下如何封装OKhttp,  发送一个网络请求需要三个功能模块,分别是 Request处理,OKhttp核心处理,callback处理  如下图所示:


首先进行第一部分Request处理部分的封装,直接上代码吧,代码中都有注释的


1:RequestParams文件用于封装所有的请求到HashMap中

package com.yongninggo.ok_http.Request;

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

/**
* @author 小马哥
* @function 封装所有的请求参数到HashMap中
*/

public class RequestParams {

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

public RequestParams (){
this((Map<String,String>)null);
}

public RequestParams(Map<String, String> source) {
if (source != null) {
for (Map.Entry<String, String> entry : source.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
}

public RequestParams(final String key, final String value) {
this(new HashMap<String, String>() {
{
put(key, value);
}
});
}

//将key对应的value放置urlParams <HashMap> 中
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;
}

}

2: CommonRequest文件类,用于接收请求参数,为我们生成Request对象  (2个方法 (Post and Get))

package com.yongninggo.ok_http.Request;

import java.util.Map;

import okhttp3.FormBody;
import okhttp3.Request;

/**
* @author 小马哥
* @function 接收请求参数,为我们生成request对象
*/

public class CommonRequest {

/**
*
* @param url
* @param params
* @return 返回一个创建好的request对象
*/
public static Request CreatePostRequest (String url,RequestParams params){
//构建者对象
FormBody.Builder FormBodyBuilder = new FormBody.Builder();

if (params != null) {
for (Map.Entry<String,String>entry :params.urlParams.entrySet()){
//将请求参数添加到请求构建类中
FormBodyBuilder.add(entry.getKey(),entry.getValue());
}
}
//通过build方法获取到真正的请求体对象
FormBody formBody = FormBodyBuilder.build();
return new Request.Builder().url(url).post(formBody).build();
}

/**
*
* @param url
* @param params
* @return 返回一个Get类型的请求
*/
public static Request CreateGetRequest (String url,RequestParams params){
//因为涉及到字符串的拼接,所以使用stringbuilder的效率更高 Get请求‘问号后面带参数’
StringBuilder urlBuilder = new StringBuilder(url).append("?");
if (params != null) {
for (Map.Entry<String,String>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();
}

}

到目前为止,Request处理部分已经完成了封装 接下来进行核心OKhttp进行封装



commonokhttpClient类是对okhttp进行封装,完成发送请求,参数的配置,https的支持
package com.yongninggo.ok_http;

import com.yongninggo.ok_http.https.HttpsUtils;

import java.util.concurrent.TimeUnit;

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

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

/**
* @function 请求发送,请求参数的配置,https的支持
* @author 小马哥
*/

public class CommonOkhttpClient {

private static final int TIME_OUT = 30; //超时参数为30秒
private static OkHttpClient okHttpClient;

//为我们的Client配置参数
static {
//创建构建者对象
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
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;
}
});
//设置SSLFactory
okHttpBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());
//生成Client对象
okHttpClient = okHttpBuilder.build();
}

//发送具体的请求 返回Call
public static Call sendRequest (Request request, okhttp3.Callback callback){

Call call = okHttpClient.newCall(request);
call.enqueue(callback);
return call;
}

}

HttpsUtils文件是设置加密的SSLfactory的信任管理类

package com.yongninggo.ok_http.https;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.X509TrustManager;/** * Created by 14487 on 2017/6/30. */public class HttpsUtils {    //生成一个加密类型的SSLSocketFactory    public static SSLSocketFactory getSslSocketFactory (){        //1:生成一个信任管理器类        X509TrustManager trustManager = new X509TrustManager() {            @Override            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {            }            @Override            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {            }            @Override            public X509Certificate[] getAcceptedIssuers() {                return new X509Certificate[0];            }        };        //2:创建加密上下文        SSLContext sslContext = null;        try {            //和服务器要保持一致的算法类型            sslContext = SSLContext.getInstance("SSL");            X509TrustManager[] trustArray = new X509TrustManager[]{                    trustManager            };            sslContext.init(null,trustArray,new SecureRandom());        }        catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        catch (KeyManagementException e) {            e.printStackTrace();        }        return sslContext.getSocketFactory();    }}



前两步的封装现在已经完成了,就剩Callback的封装了。

callback需要处理的功能有 1:处理异常; 2:转发消息到UI线程 ;  3:将json转化成对应的实体对象  3:执行回调

先新建2个文件 DisposeDataListener 处理我们的自定义监听事件:成功,失败,下载,上传操作等
package com.yongninggo.ok_http.listener;

/**
* 自定义事件监听
*/

public interface DisposeDataListener {
//请求失败调用
public void onFailure (Object responseObj);


//请求成功调用
public void onSuccess (Object reasonObj);
}

DisposeDataHandle 处理json对象到实体对象的转换
package com.yongninggo.ok_http.listener;

/**
* @author chao
* @function json对象装换成实体对象
*/

public class DisposeDataHandle {

public DisposeDataListener listener = null;
public Class<?> aClass = null;

//数据原封不动
public DisposeDataHandle(DisposeDataListener listener){
this.listener = listener;
}
//数据转化为json实体对象
public DisposeDataHandle (DisposeDataListener listener,Class<?> clazz){
this.listener = listener;
this.aClass = clazz;
}
}

上面是作为回调内容的处理功能,主要啊功能在CommonJSonCallback中实现:

首先建一个Exception用来收集所有的错误信息
package com.yongninggo.ok_http.Exception;

/**
* @author chao
* @function 自定义异常处理
*/

public class OkhttpException extends Exception {
private static final long serialVersionUID = 1L;
private int ecode;
private Object emsg;
public OkhttpException(int ecode,Object emsg){
this.ecode = ecode;
this.emsg = emsg;
}
public int getEcode (){
return ecode;
}
public Object getEmsg (){
return emsg;
}
}

 


好了,完成jsoncallback代码附上,此时封装基本就已经实现了,接下来测试调用看是否成功。

package com.yongninggo.ok_http.Response;

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

import com.yongninggo.ok_http.Exception.OkhttpException;
import com.yongninggo.ok_http.listener.DisposeDataHandle;
import com.yongninggo.ok_http.listener.DisposeDataListener;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Response;


/**
* @function 处理json的回调响应
*/

public class CommonjsonCallback {

//与服务器返回字段的对应关系
protected final String RESULT_CODE = "exode";
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 Handler mDeliveryHandler;//进行消息的转发,将子线程的数据转发到UI线程
private DisposeDataListener Listener;
private Class<?> aClass;

public CommonjsonCallback (DisposeDataHandle handle){
this.Listener = handle.listener;
this.aClass = handle.aClass;
this.mDeliveryHandler = new Handler(Looper.getMainLooper());
}

//请求失败处理
public void onFailure (final Call call, final IOException e){
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
//失败的话将信息传入Exception中
Listener.onFailure(new OkhttpException(NETWORK_ERROR,e));
}
});
}

//请求成功响应处理
public void onResponse (final Call call, final Response response) throws IOException{
final String result = response.body().string();
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
handleResponse (result);
}

});
}
//处理服务器返回的响应数据
private void handleResponse(Object responseObj) {
//为了保证代码的健壮性
if (responseObj == null && responseObj.toString().trim().equals(" ")){
Listener.onFailure(new OkhttpException(NETWORK_ERROR,EMPTY_MSG));
return;
}

try {
//开始尝试解析json
JSONObject reuslt = new JSONObject(responseObj.toString());
//从json对象中取出我们的响应码,若为0(与服务器一致),则是正常的响应
if (reuslt.has(RESULT_CODE)){
if (reuslt.getInt(RESULT_CODE) == RESULT_CODE_VALUE){
if (aClass == null) {
Listener.onSuccess(responseObj);
} else {
//将json对象转化为实体对象
Gson gson = new Gson();
Object obj = gson.fromJson(responseObj.toString(),aClass);

if (obj != null) {
Listener.onSuccess(obj);
} else {
//返回的不是合法的json
Listener.onFailure(new OkhttpException(JSON_ERROR,EMPTY_MSG));
}
}
}
else {
//将服务器返回给我们的异常回调到应用层去处理
Listener.onFailure(new OkhttpException(OTHER_ERROR,reuslt.get(RESULT_CODE)));
}
}
}
catch (JSONException e) {
Listener.onFailure(new OkhttpException(OTHER_ERROR,e.getMessage()));
}

}
}


将json转化为实体对象是利用Gson转json的,  其实就是添加一个json的依赖,在下载一个GsonFormat就可以了。 (这一步可以百度就知道了)

测试调用格式
private void test (){
CommonOkhttpClient.sendRequest(CommonRequest.CreateGetRequest("http://www.baidu.com/",null),new CommonJsonCallback(new DisposeDataHandle(new DisposeDataListener() {
@Override
public void onFailure(Object responseObj) {

}

@Override
public void onSuccess(Object reasonObj) {


}
})));
}

测试成功,  over。

源码下载地址 :OKhttp封装



智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
China Scenic Area
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告