Android--okhttp框架封装思路/网络请求组件的创建

封装目的

规避okhttp框架API更新带来的风险
提高代码复用性
提升程序的可扩展性

封装逻辑

封装逻辑

封装思路

封装思路--思维导图

1.封装request

RequestParams类
    封装所有的请求参数到HashMap中(线程安全)
CommonRequest类
    接受请求参数,生成request对象
RequestParams类
    封装所有的请求参数到HashMap中(线程安全)
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xiaoxu 17-07-21
 * @function 封装所有的请求参数到HashMap中(线程安全)
 */
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;
    }
}
CommonRequest类
    接受请求参数,生成request对象
import java.util.Map;

import okhttp3.FormBody;
import okhttp3.Request;

/**
 * Created by xiaoxu on 2017/7/22.
 *
 * @function 接受请求参数,生成request对象
 */
public class CommonRequest {

    /**
     * @param url
     * @param params
     * @return 返回一个创建好的post类型request对象
     */
    public static Request createPostRequest(String url, RequestParams params) {
        //获取构建者
        FormBody.Builder mFormBodyBuilder = new FormBody.Builder();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
                //将请求参数遍历添加到请求构建类中
                mFormBodyBuilder.add(entry.getKey(), entry.getValue());
            }
        }
        //通过请求构建类的build方法获取到真正的【请求体】对象
        FormBody mFromBody = mFormBodyBuilder.build();
        return new Request.Builder().url(url).post(mFromBody).build();
    }


    /**
     * @param url
     * @param params
     * @return 返回一个get类型请求对象
     */
    public static Request createGetRequest(String url, RequestParams params) {
        //StringBuilder 效率更高
        StringBuilder urlBuilder = new StringBuilder(url).append("?");
        if (params != null) {
            for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
                //将请求参数遍历添拼接到url中
                urlBuilder.append(entry.getKey())
                        .append("=")
                        .append(entry.getValue())
                        .append("&");
            }
        }

        return new Request.Builder()
                .url(urlBuilder.substring(0, urlBuilder.length() - 1))
                .get()
                .build();
    }

}

2.封装client

CommonOkthhpClient类
    请求体发送,请求参数的配置,https的支持
import com.yingyuliuliwan.liuliwansdk.okhttps.https.HttpsUtils;
import com.yingyuliuliwan.liuliwansdk.okhttps.response.CommonJsonCallback;
import java.util.concurrent.TimeUnit;

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

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

/**
 * Created by xiaoxu on 2017/7/22.
 *
 * @function 请求体发送,请求参数的配置,https的支持
 */
public class CommonOkthhpClient {
    private static final int TIME_OUT = 30000;
    private static OkHttpClient mOkHttpClient;

    //使用静态代码块设置请求参数,保证mOkHttpClient对象所有实例的参数都一致
    static {
        //client对象的构建者
        OkHttpClient.Builder okhttpBulider = new OkHttpClient.Builder();
        //为构建者他填充超时时间
        okhttpBulider.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
        okhttpBulider.readTimeout(TIME_OUT, TimeUnit.SECONDS);
        okhttpBulider.writeTimeout(TIME_OUT, TimeUnit.SECONDS);

        okhttpBulider.followRedirects(true);
        //添加https支持(表示客户端支持所有类型证书的的https请求)
        okhttpBulider.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                //无论主机名是什么都返回true
                return true;
            }
        });
        okhttpBulider.sslSocketFactory(HttpsUtils.initSSLSocketFactory());

        //生成client对象
        mOkHttpClient = okhttpBulider.build();
    }

    public static Call sendRequest(Request request, CommonJsonCallback commonCallBack){

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(commonCallBack);
        return call;

    }
}

3.封装response

DisposeDataListener类
    自定义监听事件,回调事件处理
DisposeDataHandle类
    将回调监听对象和要转化的字节码进行封装
CommonJsonCallback类
    处理json的回调响应
ResponseEntityToModule类
    将json对象转化为实体类对象(也可以使用第三方库)
DisposeDataListener类
    自定义监听事件,回调事件处理
/**
 * Created by xiaoxu on 2017/7/23.
 * 添加事件监听(防止框架回调API的改变,增加扩展性)
 */
public interface DisposeDataListener {

    /**
     * 请求成功回调事件处理
     */
    public void onSuccess(Object responseObj);

    /**
     * 请求失败回调事件处理
     */
    public void onFailure(Object reasonObj);

}
DisposeDataHandle类
    将回调监听对象和要转化的字节码进行封装
/**
 * Created by Administrator on 2017/7/23.
 *  将回调监听对象和要转化的字节码进行封装
 */
public class DisposeDataHandle {

    public DisposeDataListener mListener = null;
    public Class<?> mClass = null;

    public DisposeDataHandle(DisposeDataListener mListener) {
        this.mListener = mListener;
    }

    public DisposeDataHandle(Class<?> mClass, DisposeDataListener mListener) {
        this.mClass = mClass;
        this.mListener = mListener;
    }
}
CommonJsonCallback类
    处理json的回调响应,返回callBack对象
import android.os.Handler;
import android.os.Looper;

import com.yingyuliuliwan.liuliwansdk.adutil.ResponseEntityToModule;
import com.yingyuliuliwan.liuliwansdk.okhttps.exception.OkHttpException;
import com.yingyuliuliwan.liuliwansdk.okhttps.listener.DisposeDataHandle;
import com.yingyuliuliwan.liuliwansdk.okhttps.listener.DisposeDataListener;

import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.Response;

/**
 * Created by xiaoxu on 2017/7/23.
 */
public class CommonJsonCallback implements Callback {

    //与服务器返回的字段的一个关系
    protected final String RESULT_CODE = "ecode"; // 有返回则对于http请求来说是成功的,但还有可能是业务逻辑上的错误
    protected final int RESULT_CODE_VALUE = 0;
    protected final String ERROR_MSG = "emsg";
    protected final String EMPTY_MSG = "";
    protected final String COOKIE_STORE = "Set-Cookie"; // decide the server it
    // can has the value of
    // set-cookie2

    /**
     * 自定义异常类型
     */
    protected final int NETWORK_ERROR = -1; // the network relative error
    protected final int JSON_ERROR = -2; // the JSON relative error
    protected final int OTHER_ERROR = -3; // the unknow error

    /**
     * 将其它线程的数据转发到UI线程
     */
    private Handler mDeliveryHandler;
    private DisposeDataListener mListener;
    private Class<?> mClass;

    public CommonJsonCallback(DisposeDataHandle handle) {
        this.mListener = handle.mListener;
        this.mClass = handle.mClass;
        this.mDeliveryHandler = new Handler(Looper.getMainLooper());
    }

    //请求失败处理
    @Override
    public void onFailure(final Call call, final IOException ioexception) {
        /**
         * 此时还在非UI线程,因此要转发
         */
        mDeliveryHandler.post(new Runnable() {
            @Override
            public void run() {
                mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
            }
        });
    }

    //真正的响应处理函数
    @Override
    public void onResponse(final Call call, final Response response) throws IOException {
        //获取返回的字符串
        final String result = response.body().string();
        final ArrayList<String> cookieLists = handleCookie(response.headers());
        //将字符串转发给主线程
        mDeliveryHandler.post(new Runnable() {
            @Override
            public void run() {
                handleResponse(result);
                /**后续升级准备
                 * handle the cookie
                 */
                /*if (mListener instanceof DisposeHandleCookieListener) {
                    ((DisposeHandleCookieListener) mListener).onCookie(cookieLists);
                }*/
            }
        });
    }

   /* private ArrayList<String> handleCookie(Headers headers) {
        ArrayList<String> tempList = new ArrayList<String>();
        for (int i = 0; i < headers.size(); i++) {
            if (headers.name(i).equalsIgnoreCase(COOKIE_STORE)) {
                tempList.add(headers.value(i));
            }
        }
        return tempList;
    }*/

    //处理服务器返回的响应数据
    private void handleResponse(Object responseObj) {
        //为了保障代码的健壮性,进行判空处理
        if (responseObj == null || responseObj.toString().trim().equals("")) {
            mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG));
            return;
        }

        try {
             /*
            * 协议确定后看这里如何修改
            */
            JSONObject result = new JSONObject(responseObj.toString());
            //判断http请求是否成功
            if (result.has(RESULT_CODE)){
                //从json数据中获取响应码,是否为定义的正常的响应码
                if (result.getInt(RESULT_CODE)==RESULT_CODE_VALUE){
                    if (mClass == null) {
                        //不需要转化为实体对象,直接返回数据到应用层
                        mListener.onSuccess(result);
                    } else {
                        // 需要将json对象转化为实体类对象(自己创建的,也可以使用第三方库)
                        Object obj = ResponseEntityToModule.parseJsonObjectToModule(result, mClass);
                        //判断是否正确的转化为实体类对象
                        if (obj != null) {
                            mListener.onSuccess(obj);
                        } else {
                            //返回的是一个不合法的json
                            mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG));
                        }
                    }
                }
            }

        } catch (Exception e) {
            mListener.onFailure(new OkHttpException(OTHER_ERROR, e.getMessage()));
            e.printStackTrace();
        }
    }
}

ResponseEntityToModule类
    将json对象转化为实体类对象(也可以使用第三方库)
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;

import io.realm.RealmList;
import io.realm.RealmModel;
import io.realm.RealmObject;

/**********************************************************
 * @文件名称:ResponseEntityToModule.java
 * @文件作者:qndroid
 * @创建时间:2015年7月31日 上午10:51:44
 * @文件描述:递归ORM映射(有反射,不能被混淆)
 * @修改历史:2015年7月31日创建初始版本
 **********************************************************/
public class ResponseEntityToModule {

    public static Object parseJsonToModule(String jsonContent, Class<?> clazz) {
        Object moduleObj = null;
        try {
            JSONObject jsonObj = new JSONObject(jsonContent);
            moduleObj = parseJsonObjectToModule(jsonObj, clazz);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return moduleObj;
    }

    public static Object parseJsonObjectToModule(JSONObject jsonObj, Class<?> clazz) {
        Object moduleObj = null;
        try {
            moduleObj = (Object) clazz.newInstance();
            setFieldValue(moduleObj, jsonObj, clazz);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return moduleObj;
    }

    public static RealmObject parseJsonObjectToRealmModel(JSONObject jsonObj, Class<?> clazz) {
        RealmObject moduleObj = null;
        try {
            moduleObj = (RealmObject) clazz.newInstance();
            setFieldValue(moduleObj, jsonObj, clazz);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return moduleObj;
    }

    private static void setFieldValue(Object moduleObj, JSONObject jsonObj, Class<?> clazz)
            throws IllegalArgumentException, IllegalAccessException, JSONException, InstantiationException {
        if (clazz.getSuperclass() != null) {
            setFieldValue(moduleObj, jsonObj, clazz.getSuperclass());
        }
        Field[] fields = clazz.getDeclaredFields();
        Class<?> cls;
        String name;
        for (Field f : fields) {
            f.setAccessible(true);
            cls = f.getType();
            name = f.getName();
            if (!jsonObj.has(name) || jsonObj.isNull(name)) {
                continue;
            }
            if (cls.isPrimitive() || isWrappedPrimitive(cls))
            {
                setPrimitiveFieldValue(f, moduleObj, jsonObj.get(name));
            } else {
                if (cls.isAssignableFrom(String.class)) {
                    f.set(moduleObj, String.valueOf(jsonObj.get(name)));
                } else if (cls.isAssignableFrom(ArrayList.class)) {
                    parseJsonArrayToList(f, name, moduleObj, jsonObj);
                }
                //在这儿可以加个判断,如果是RealmList类型则转化为RealmList,方便直接存入数据库
                else if (cls.isAssignableFrom(RealmList.class)) {
                    parseJsonArrayToRealmList(f, name, moduleObj, jsonObj);
                } else {
                    Object obj = parseJsonObjectToModule(jsonObj.getJSONObject(name), cls.newInstance().getClass());
                    f.set(moduleObj, obj);
                }
            }
        }
    }

    private static RealmList<RealmObject> parseJsonArrayToRealmList(Field field, String fieldName, Object moduleObj,
                                                                   JSONObject jsonObj) throws JSONException, IllegalArgumentException, IllegalAccessException {
        RealmList<RealmObject> objList = new RealmList<>();
        Type fc = field.getGenericType();
        if (fc instanceof ParameterizedType)
        {
            ParameterizedType pt = (ParameterizedType) fc;
            if (pt.getActualTypeArguments()[0] instanceof Class)
            {
                Class<?> clss = (Class<?>) pt.getActualTypeArguments()[0];

                if (jsonObj.get(fieldName) instanceof JSONArray) {
                    JSONArray array = jsonObj.getJSONArray(fieldName);
                    for (int i = 0; i < array.length(); i++) {
                        if (array.get(i) instanceof JSONObject) {
                            objList.add(parseJsonObjectToRealmModel(array.getJSONObject(i), clss));
                        } else {
                            if (clss.isAssignableFrom(array.get(i).getClass())) {
                                objList.add((RealmObject) array.get(i));
                            }
                        }
                    }
                }
                field.set(moduleObj, objList);
            }
        }
        return objList;
    }

    private static ArrayList<Object> parseJsonArrayToList(Field field, String fieldName, Object moduleObj,
                                                          JSONObject jsonObj) throws JSONException, IllegalArgumentException, IllegalAccessException {
        ArrayList<Object> objList = new ArrayList<Object>();
        Type fc = field.getGenericType();
        if (fc instanceof ParameterizedType)
        {
            ParameterizedType pt = (ParameterizedType) fc;
            if (pt.getActualTypeArguments()[0] instanceof Class)
            {
                Class<?> clss = (Class<?>) pt.getActualTypeArguments()[0];

                if (jsonObj.get(fieldName) instanceof JSONArray) {
                    JSONArray array = jsonObj.getJSONArray(fieldName);
                    for (int i = 0; i < array.length(); i++) {
                        if (array.get(i) instanceof JSONObject) {
                            objList.add(parseJsonObjectToModule(array.getJSONObject(i), clss));
                        } else {
                            if (clss.isAssignableFrom(array.get(i).getClass())) {
                                objList.add(array.get(i));
                            }
                        }
                    }
                }
                field.set(moduleObj, objList);
            }
        }
        return objList;
    }

    private static void setPrimitiveFieldValue(Field field, Object moduleObj, Object jsonObj)
            throws IllegalArgumentException, IllegalAccessException {
        if (field.getType().isAssignableFrom(jsonObj.getClass())) {
            field.set(moduleObj, jsonObj);
        } else {
            field.set(moduleObj, makeTypeSafeValue(field.getType(), jsonObj.toString()));

        }
    }

    private static final Object makeTypeSafeValue(Class<?> type, String value) throws NumberFormatException,
            IllegalArgumentException {
        if (int.class == type || Integer.class == type) {
            return Integer.parseInt(value);
        } else if (long.class == type || Long.class == type) {
            return Long.parseLong(value);
        } else if (short.class == type || Short.class == type) {
            return Short.parseShort(value);
        } else if (char.class == type || Character.class == type) {
            return value.charAt(0);
        } else if (byte.class == type || Byte.class == type) {
            return Byte.valueOf(value);
        } else if (float.class == type || Float.class == type) {
            return Float.parseFloat(value);
        } else if (double.class == type || Double.class == type) {
            return Double.parseDouble(value);
        } else if (boolean.class == type || Boolean.class == type) {
            return Boolean.valueOf(value);
        } else {
            return value;
        }
    }

    private static boolean isWrappedPrimitive(Class<?> type) {
        if (type.getName().equals(Boolean.class.getName()) || type.getName().equals(Byte.class.getName())
                || type.getName().equals(Character.class.getName()) || type.getName().equals(Short.class.getName())
                || type.getName().equals(Integer.class.getName()) || type.getName().equals(Long.class.getName())
                || type.getName().equals(Float.class.getName()) || type.getName().equals(Double.class.getName())) {
            return true;
        }
        return false;
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值