Okhttp3网络请求框架简析思考——Android网络请求框架(五)

站在世界的巅峰看世界的心情,决不是一个普通人可以体会的到的感受java

一、对单例设计模式的思考 

建立方式一 、

/**
 * Created by androidlongs on 16/9/12.
 * 站在顶峰,看世界
 * 落在谷底,思人生
 */

/**
 * 建立方式一:
 * 
 * 当在JVM在加载单例类的时候,单例对象就会被创建
 * 当其中有其余的静态方法的时候,使用类调用方法,没有使用到该单例对象,可是单例对象也会被建立出来,从而形成了资源的浪费
 */
public class Singleton {
    //直接建立
    public static  Singleton sSingleton = new Singleton();
    //私有构造函数
    private Singleton(){

    }
    //返回对象体
    public static Singleton getInstance(){
        return sSingleton;
    }
    //获取String的方法
    public static String getString(){
        return "single";
    }

}

建立方式 二

/**
 * Created by androidlongs on 16/9/12.
 * 站在顶峰,看世界
 * 落在谷底,思人生
 */

/**
 * 建立方式二
 *
 * 有点性能上的损失
 */
class SingletonLazy{
    //声明变量
    public static  SingletonLazy sSingletonLazy;
    //私有构造函数
    private SingletonLazy(){

    }
    //提供对外方法
    public static  SingletonLazy getInstance(){
        if (sSingletonLazy == null) {
            synchronized (SingletonLazy.class){
                if (sSingletonLazy == null) {
                    sSingletonLazy = new SingletonLazy();
                }
            }
        }
        return sSingletonLazy;
    }

    //获取String的方法
    public static  String getString(){
        return "single";
    }


}

建立方式三:

/**
 * 建立方式三
 */
class  CommonSingleton{
    //私有构造
    private CommonSingleton(){

    }
    //提供对外方法
    public static CommonSingleton getInstance(){
        return  SingletonHolder.commonSingleton;
    }
    //内部类方法维护
    private static class SingletonHolder{
        private static CommonSingleton commonSingleton = new CommonSingleton();
    }
    //获取String的方法
    public static String getString(){
        return "single";
    }

}

分析 简述:android

    1-一、能够看到上面三种建立单例的方法,第一种方式被传统命名为饿汉式,单例对象随着类的加载而被建立,当咱们使用类中的其余静态方法而没有使用到单例对象的时候,单例对象依然会被建立出来,从某种角度来讲,形成了必定的内存浪费。json

    1-二、第二种方式被传统命名为懒汉式,也就是在调用实例化对象的时候,才会将单例对象建立出来,当咱们使用类中的其余静态方法的时候,会同时有单例对象的null引用生成,在必定程度上会很消耗内存,再者建立实例化对象的时候,双重非空锁判断,也是至关消耗性能的工做。设计模式

    1-三、第三种方式能够称为是完美设计版了,由于它能够解决前两种设计方法的不足之处,当去调用类的实例化方法的时候,单例对象才会被建立,而当调用类中的其余静态方法的时候,对静态单例对象没有任何的操做,因此能够说是比较完美的了,之因此能够称为比较而不是彻底,是因使用这种方式建立,在进行序列化与反序列化的时候,会出现非单例对象问题。缓存

二、使用单例设计模式来建立Okhttp网络请求框架

/**
 * Created by androidlongs on 16/9/12.
 * 站在顶峰,看世界
 * 落在谷底,思人生
 */
public class CommonOkhttpUtils {
    //私有化构造
    private CommonOkhttpUtils(){
        //初始化Okhttp配制
        initOkHttpFunction();
    }

    //提供实例化对象 
    public static CommonOkhttpUtils getUtilsInstance(){
        return  OkHttpSingle.sCommonOkhttpUtils;
    }
    //实例静态内部类
    private static class OkHttpSingle{
        private static CommonOkhttpUtils sCommonOkhttpUtils = new CommonOkhttpUtils();
    }


    //初始化Okhttp配制
    private void initOkHttpFunction() {
        
    }
}

固然在使用Okhttp3的时候 要先关联依赖markdown

compile 'com.squareup.okhttp3:okhttp:3.3.1'

三、对Okhttp3进行的一些初始化配制 

private OkHttpClient mOkHttpClient;
    //初始化Okhttp配制
    private void initOkHttpFunction() {
        //配制网络数据缓存
        File cacheDirectory = APPApplication.getmContext().getExternalCacheDir();
        //配制网络数据缓存大小  10M
        int cacheSize = 10*1024*1024;
        //
        Cache cache = new Cache(cacheDirectory,cacheSize);
        //建立HttpClientBuilder
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        //设置缓存 以及超时间 以及获取OkHttpClient对象
        mOkHttpClient = builder.writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .cache(cache)
                .build();
    }

四、网络请求思路综述

    其实建立一个网络链接并无多复杂网络

    4-1 建立请求Request对象 app

    4-2建立封装参数的RequestBody对象(GET方法除外)框架

    4-3 封装请求参数 异步

    4-4 建立请求Response对象实例

    4-5 发起网络请求

    4-6 处理回调监听

    4-7 处理取消网络请求标签    

五、GET异步请求(可传参数 )

/**
     * 异步GET网络请求
     *
     * @param url          请求网络连接
     * @param headerMap    请求网络添加头信息
     * @param paramsMap    请求网络参数
     * @param cacheControl 缓存模式
     *                    
     *                     public static final CacheControl FORCE_NETWORK = ..;
     *                     
     *                     public static final CacheControl FORCE_CACHE = ...
     * @param callback     响应回调
     * @param tag          网络任务标识
     */
    public void okHttpGetRequest(String url, Map<String, String> headerMap, Map<String, String> paramsMap, CacheControl cacheControl, Callback callback, String tag) {

        //GET请求-1 封装请求参数 
        //Get请求传参数其实是在请求连接中携带参数 
        StringBuilder sb = new StringBuilder();
        sb.append(url).append("?");
        
        if (paramsMap != null && !paramsMap.isEmpty()) {
            for (String key : paramsMap.keySet()) {
                sb.append(key).append("=").append(paramsMap.get(key)).append("&");
            }
            sb = sb.deleteCharAt(sb.length() - 1);
            url = sb.toString();
        }
        
        //GET请求-2 获取Builder
        Request.Builder builder = new Request.Builder().url(url);
        
        //GET请求-3 设置缓存
        if (cacheControl != null) {
            builder.cacheControl(cacheControl);
        }
        //GET请求-4添加请求头信息
        if (headerMap != null && !headerMap.isEmpty()) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        //GET请求-5 建立请求Request对象 
        Request request = builder.build();
        //GET请求-6 设置取消标签
        Call call = mOkHttpClient.newCall(request);
        //将请求标签添加到请求Key集合中
        mCallHashMap.put(tag, call);
        //GET请求-5 发起网络请求
        call.enqueue(callback);
    }

    /**
     * 移除 取消网络任务
     *
     * @param tag
     */
    public void removeRequest(String tag) {
        //获取KEY的集合
        Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
        //若是包含KEY
        if (keyEntries.contains(tag)) {
            //获取对应的Call
            Call call = mCallHashMap.get(tag);
            //若是没有被取消 执行取消的方法
            if (!call.isCanceled()) {
                call.cancel();
            }
            //移除对应的KEY
            mCallHashMap.remove(tag);
        }
    }

这是GET请求参数最多的方法,咱们能够在此基础上封装少参数的方法,例如不须要设置请求头,请求参数,不指定缓存模式,对应的传入null就能够。这里实际上就是将传入的参数以KEY - VALUE的方式拼接在了请求连接中

对于网络请求模式,默认有两种,一是强制使用网络请求数据 ,一是强制使用缓存,通常使用默认使用网络请求就能够

使用案例 :

//GET访问
    private void getRequestFunction() {
        //请求连接
        String url = "";
        //网络请求标识
        String tag = "getRequest";

        //提交参数 
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("userName", "xxx");
        paramMap.put("password", "123456");


        //添加请求Header 
        Map<String, String> heardMap = new HashMap<>();
        heardMap.put("verson", "11");


        CommonOkhttpUtils.getUtilsInstance().okHttpGetRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            //请求失败回调方法
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
            //请求成功回调方法
            }
        }, tag);
    }
    
    
    //取消网络请求
    private void canlaneRequest(String tag){
        CommonOkhttpUtils.getUtilsInstance().removeRequest(tag);
    }

经过抓包能够看到咱们提交的请求数据为

六、POST异步请求提交表单数据 

/**
     * 异步POST网络请求  提交表单数据
     *
     * @param url          请求网络连接
     * @param headerMap    请求网络添加头信息
     * @param parmMap    请求网络参数
     * @param cacheControl 缓存模式
     *                     public static final CacheControl FORCE_NETWORK = ..;
     *                    
     *                     public static final CacheControl FORCE_CACHE = ...
     * @param callback     响应回调
     * @param tag          网络任务标识
     */
    public void okPostFormRequest(String url, Map<String, String> headerMap, Map<String, String> parmMap, CacheControl cacheControl, Callback callback, String tag) {
        //POST - FORM 表单 获取请求参数BODY
        FormBody.Builder formBuilder = new FormBody.Builder();

        //POST - FORM 表单 封装参数
        if (parmMap != null && !parmMap.isEmpty()) {
            for (Map.Entry<String, String> entry : parmMap.entrySet()) {
                formBuilder.add(entry.getKey(), entry.getValue());
            }
        }

        //POST - FORM 获取表单BODY
        RequestBody formBody = formBuilder.build();
        //POST - FORM 构建请求Request Builder
        Request.Builder requestBuilder = new Request.Builder().url(url);

        //POST - FORM 设置缓存

        if (cacheControl != null) {
            requestBuilder.cacheControl(cacheControl);
        }

        //POST - FORM 添加请求头信息
        if (headerMap != null && !headerMap.isEmpty()) {
            for (Map.Entry<String, String> entry :
                    headerMap.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        //POST - FORM 构建请求Request
        Request request = requestBuilder.post(formBody).build();
        //POST - FORM 构建请求响应Call
        Call call = mOkHttpClient.newCall(request);
        //POST - FORM 设置取消任务标签 
        mCallHashMap.put(tag,call);
        //POST - FORM 发起请求
        call.enqueue(callback);
    }

    /**
     * 移除 取消网络任务
     *
     * @param tag
     */
    public void removeRequest(String tag) {
        //获取KEY的集合
        Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
        //若是包含KEY
        if (keyEntries.contains(tag)) {
            //获取对应的Call
            Call call = mCallHashMap.get(tag);
            //若是没有被取消 执行取消的方法
            if (!call.isCanceled()) {
                call.cancel();
            }
            //移除对应的KEY
            mCallHashMap.remove(tag);
        }
    }
}

案例:

private void postRequestForm() {
        //请求连接
        String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
        //网络请求标识
        String tag = "getRequest";

        //提交参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("userName", "xxx");
        paramMap.put("password", "123456");


        //添加请求Header
        Map<String, String> heardMap = new HashMap<>();
        heardMap.put("verson", "11");
        CommonOkhttpUtils.getUtilsInstance().okPostFormRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败回调方法
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功回调方法
            }
        }, tag);
    }

经过抓包工具能够看到提交的数据为:

提交数据的格式为: Content - Type:application/x-www-form-urlencoded

添加的请求头为 verson : 11

提交的参数为:

七、POST异步请求提交JSON数据 

/**
     * 异步POST网络请求 提交JSON数据 
     *
     * @param url          请求网络连接
     * @param headerMap    请求网络添加头信息
     * @param parmMap    请求网络参数
     * @param cacheControl 缓存模式
     *                     public static final CacheControl FORCE_NETWORK = ..;
     *                    
     *                     public static final CacheControl FORCE_CACHE = ...
     * @param callback     响应回调
     * @param tag          网络任务标识
     */
    public void okPostJSONRequest(String url, Map<String, String> headerMap, Map<String, String> parmMap, CacheControl cacheControl, Callback callback, String tag) {
        //获取Builder 
        Request.Builder builder = new Request.Builder().url(url);
       // 设置缓存
        if (cacheControl != null) {
            builder.cacheControl(cacheControl);
        }
     
       //添加请求头信息
        if (headerMap != null && !headerMap.isEmpty()) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        /**
         * 封装参数
         */
        JSONObject jsonObject = new JSONObject();
        if (parmMap != null && !parmMap.isEmpty()) {
            for (Map.Entry<String, String> entry :parmMap.entrySet()) {
                try {
                    jsonObject.put(entry.getKey(), entry.getValue());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
       
        //获取RequestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonObject.toString());
        //获取 Request
        Request request = builder.post(requestBody).build();
        //获取Call
        Call call = mOkHttpClient.newCall(request);
        //POST - JSON 设置取消任务标签
        mCallHashMap.put(tag,call);
        //POST - JSON 发起请求
        call.enqueue(callback);
    }
    /**
     * 移除 取消网络任务
     *
     * @param tag
     */
    public void removeRequest(String tag) {
        //获取KEY的集合
        Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
        //若是包含KEY
        if (keyEntries.contains(tag)) {
            //获取对应的Call
            Call call = mCallHashMap.get(tag);
            //若是没有被取消 执行取消的方法
            if (!call.isCanceled()) {
                call.cancel();
            }
            //移除对应的KEY
            mCallHashMap.remove(tag);
        }
    }

在这里,咱们将参数以map集合形式传入,而后封装成JSONObject对象,而后在构造请求体,

例 :

private void postJsonFunction() {
        //请求连接
        String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
        //网络请求标识
        String tag = "getRequest";

        //提交参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("userName", "xxx");
        paramMap.put("password", "123456");
        paramMap.put("sex", "man");


        //添加请求Header
        Map<String, String> heardMap = new HashMap<>();
        heardMap.put("verson", "11");
        CommonOkhttpUtils.getUtilsInstance().okPostJSONRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败回调方法
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功回调方法
            }
        }, tag);
    }

经过抓包工具能够看到提交的请求数据为:

请求方式为:

八、POST异步请求提交JSON数据

/**
     * 异步POST网络请求 提交JSON数据
     *
     * @param url          请求网络连接
     * @param headerMap    请求网络添加头信息
     * @param JSONBody     请求网络JSON字符串
     * @param cacheControl 缓存模式
     *                     
     *                     public static final CacheControl FORCE_NETWORK = ..;
     *                    
     *                     public static final CacheControl FORCE_CACHE = ...
     * @param callback     响应回调
     * @param tag          网络任务标识
     */
    public void okPostJSONRequest(String url, Map<String, String> headerMap, String JSONBody, CacheControl cacheControl, Callback callback, String tag) {
        //获取Builder
        Request.Builder builder = new Request.Builder().url(url);
        // 设置缓存
        if (cacheControl != null) {
            builder.cacheControl(cacheControl);
        }

        //添加请求头信息
        if (headerMap != null && !headerMap.isEmpty()) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        //获取RequestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONBody);
        //获取 Request
        Request request = builder.post(requestBody).build();
        //获取Call
        Call call = mOkHttpClient.newCall(request);
        //POST - JSON 设置取消任务标签
        mCallHashMap.put(tag, call);
        //POST - JSON 发起请求
        call.enqueue(callback);
    }

在这里,咱们将直接构造好的JSON 字符串直接传入到方法中,而后构造请求体

案例:

private void postJsonFunction1() {
        //请求连接
        String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
        //网络请求标识
        String tag = "getRequest";

        //提交参数
       String JSONString = "";

        JSONObject jsonObj = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        try {
            for (int i = 0; i < 4; i++) {
                JSONObject jsono = new JSONObject();
                jsono.put("userName", "xxx" + i);
                jsono.put("password", "123456" + i);
                jsonArray.put(jsono);
            }
            jsonObj.put("date", jsonArray);
            jsonObj.put("sex", "man");
        }catch (Exception e){

        }
        JSONString = jsonObj.toString();

        //添加请求Header
        Map<String, String> heardMap = new HashMap<>();
        heardMap.put("verson", "11");
        CommonOkhttpUtils.getUtilsInstance().okPostJSONRequest(url, heardMap,JSONString, CacheControl.FORCE_NETWORK, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败回调方法
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功回调方法
            }
        }, tag);
    }

提交的请求数据为:

{
	"date": 
    [{
		"userName": "xxx0",
		"password": "1234560"
	}, {
		"userName": "xxx1",
		"password": "1234561"
	}, {
		"userName": "xxx2",
		"password": "1234562"
	}, {
		"userName": "xxx3",
		"password": "1234563"
	}],
	"sex": "man"
}

也就是说在这里咱们能够定义任意结构层次的JSON数据

九、POST异步请求提交String 数据

/**
     * 异步POST网络请求 提交String数据
     *
     * @param url          请求网络连接
     * @param headerMap    请求网络添加头信息
     * @param string   请求网络JSON字符串
     * @param cacheControl 缓存模式
     *
     *                     public static final CacheControl FORCE_NETWORK = ..;
     *
     *                     public static final CacheControl FORCE_CACHE = ...
     * @param callback     响应回调
     * @param tag          网络任务标识
     */
    public void okPostStringRequest(String url, Map<String, String> headerMap, String string, CacheControl cacheControl, Callback callback, String tag) {
        //获取Builder
        Request.Builder builder = new Request.Builder().url(url);
        // 设置缓存
        if (cacheControl != null) {
            builder.cacheControl(cacheControl);
        }
        //添加请求头信息
        if (headerMap != null && !headerMap.isEmpty()) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        //获取RequestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"), string);
        //获取 Request
        Request request = builder.post(requestBody).build();
        //获取Call
        Call call = mOkHttpClient.newCall(request);
        //POST - JSON 设置取消任务标签
        mCallHashMap.put(tag, call);
        //POST - JSON 发起请求
        call.enqueue(callback);
    }

案例:

private void postStringFunction() {
        //请求连接
        String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
        //网络请求标识
        String tag = "getRequest";

        //提交参数
       String str = "this is String request data";
        //添加请求Header
        Map<String, String> heardMap = new HashMap<>();
        heardMap.put("verson", "11");
        CommonOkhttpUtils.getUtilsInstance().okPostStringRequest(url, heardMap, str, CacheControl.FORCE_NETWORK, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //请求失败回调方法
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求成功回调方法
            }
        }, tag);
    }

提交的数据格式 :

提交的数据原型:

 

 

十、POST源码简述:

相关文章
相关标签/搜索