OKhttp网络请求组件的封装


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


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

OKhttp网络请求组件的封装_第1张图片

首先进行第一部分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 urlParams = new ConcurrentHashMap();
    public ConcurrentHashMap fileParams = new ConcurrentHashMap();

    public RequestParams (){
        this((Map)null);
    }

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

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

    //将key对应的value放置urlParams  中
    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.Entryentry :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.Entryentry :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封装




你可能感兴趣的:(组件封装)