超简单的okhttp封装工具类(上)

时间:2021-02-08 19:44:31

 

版权声明:转载请注明出处:http://blog.csdn.net/piaomiao8179 https://blog.csdn.net/piaomiao8179/article/details/70811973

前言:

提及访问网络,很自然的会用到okHttp,虽然okhttp已经封装的比较完善,
调用也比较方便,但对于向我这样比较懒的人,okhttp的调用还是略显复杂,
每次都要写同样重复的代码,简直不能忍受,那就封装以下一句话调用完毕,岂不快哉。。。
废话不多说,请抓稳扶好,老司机,走起。。。
  • 1
  • 2
  • 3
  • 4

重要的事情提一提:看不懂的文章最后有完整代码,看看完整版应该就没问题了。

okHttp使用流程

没有什么是一张图说不清的,走起
  • 1

超简单的okhttp封装工具类(上)

高逼格的封装开始

网络访问框架一般都需要单例模式(singleton),首先我们也进行单利模式。
1 首先私有化构造器,让别人不能new出其它实例。
2 声明该类的一个静态成员变量实例,本篇为instance
3 声明一个公有的方法getInstance提供给调用者本类实例。

 /**
 * 网络访问要求singleton
 */
private static OkHttpUtils instance;

// 必须要用的okhttpclient实例,在构造器中实例化保证单一实例
private OkHttpClient mOkHttpClient;
private OkHttpUtils() {
    /**
     * okHttp3中超时方法移植到Builder中
     */
    mOkHttpClient = (new OkHttpClient()).newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();


}

public static OkHttpUtils getInstance() {
    if (instance == null) {
        synchronized (OkHttpUtils.class) {
            if (instance == null) {
                instance = new OkHttpUtils();
            }
        }
    }

    return instance;
}

上面代码在构造器中实例化出了okHttpClient的实例,既然我们这个帮助类是单例的,那么构造器中的okHttpClient也只会走一次,必定也是单实例的。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

提供GET和POST两种访问方式的方法

既然是工具类,肯定要更加简单,此处我们需要提供针对GET和POST两种方式的访问方法。
  • 1

1.工具类为GET访问方式提供的方法

 /**
 * 对外提供的Get方法访问
 * @param url
 * @param callBack
 */
public void Get(String url, MyCallBack callBack) {
    /**
     * 通过url和GET方式构建Request
     */
    Request request = bulidRequestForGet(url);
    /**
     * 请求网络的逻辑
     */
    requestNetWork(request, callBack);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2.工具类为POST访问方式提供的方法(表单数据)

/**
 * 对外提供的Post方法访问
 * @param url
 * @param parms: 提交内容为表单数据
 * @param callBack
 */
public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) {
    /**
     * 通过url和POST方式构建Request
     */
    Request request = bulidRequestForPostByForm(url, parms);
    /**
     * 请求网络的逻辑
     */
    requestNetWork(request, callBack);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.工具类为POST访问提供方法(JSON数据)

 /**
 * 对外提供的Post方法访问
 * @param url
 * @param json: 提交内容为json数据
 * @param callBack
 */
public void PostWithJson(String url, String json, MyCallBack callBack) {
    /**
     * 通过url和POST方式构建Request
     */
    Request request = bulidRequestForPostByJson(url, json);
    /**
     * 请求网络的逻辑
     */
    requestNetWork(request, callBack);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

从这两个方法,我们能看到我们需要构建GET和POST访问方式对应的Request对象和我们自定义的MycallBack接口,下面先来看一下构建Request对象。

构建Request对象

为了大家更好的理解封装流程,首先请大家回顾一下okhttp的使用流程:
mOkHttpClient.newCall(request).enqueue(new Callback() {})
  • 1
  • 2

1.首先我们来看构建GET需要的Request对象,这个也是最简单的。

  /**
 * GET方式构建Request
 * @param url
 * @return
 */
private Request bulidRequestForGet(String url) {

    return new Request.Builder()
            .url(url)
            .get()
            .build();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.构建提交表单数据的Request对象

/**
 * POST方式构建Request {Form}
 * @param url
 * @param parms
 * @return
 */
private Request bulidRequestForPostByForm(String url, Map<String, String> parms) {

    FormBody.Builder builder = new FormBody.Builder();

    if (parms != null) {
        for (Map.Entry<String, String> entry :
                parms.entrySet()) {
            builder.add(entry.getKey(), entry.getValue());
        }

    }
    FormBody body = builder.build();


    return new Request.Builder()
            .url(url)
            .post(body)
            .build();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

3.构建提交json数据的Request对象

 /**
 * POST方式构建Request {json}
 * @param url
 * @param json
 * @return
 */
private Request bulidRequestForPostByJson(String url, String json) {
    RequestBody body = RequestBody.create(JSON, json);

    return new Request.Builder()
            .url(url)
            .post(body)
            .build();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

开始处理联网逻辑

上述代码及分析基本上把简单封装的东西讲完了,有了okhttpclient和request对象我们需要处理联网逻辑了,也就是上述的 requestNetWork方法。

 private void requestNetWork(Request request, MyCallBack callBack) {

    /**
     * 处理连网逻辑,此处只处理异步操作enqueue
     */
    callBack.onLoadingBefore(request);

    mOkHttpClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            callBack.onFailure(request, e);
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                callBack.onSuccess(response);
            } else {
                callBack.onError(response);
            }
        }
    });


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

MyCallBack对象分析

看到此处,估计有人会一脸懵逼,这个MyCallBack是个什么鬼。
其实这是我定义的一个接口,那么为什么要定义她呢。因为我们在使用我们的工具类的时候,访问网络成功后肯定会有数据返回,我们怎么处理呢,okhttp内部通过一个callBack把数据回调回来,那么我们自己封装的工具类不妨仿照他的做法  定义一个接口回调Response的内容。贴一下接口的内容

interface MyCallBack {

void onLoadingBefore(Request request);

void onSuccess(Response response);

void onFailure(Request request, Exception e);

void onError(Response response);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

}

封装进阶

看到此处,觉得封装已经完结了,不不不,还有一个重要的问题,不处理的话会导致崩溃的,这个问题就是,我们定义接口回调的地方是在子线程,而我们的Response很明显需要拿回到主线程进行UI的更新,所以访问网络的方法requestNetWork需要通过Handler把子线程的Resonse发送到主线程,请看详细实现。
private void requestNetWork(Request request, MyCallBack callBack) {

    /**
     * 处理连网逻辑,此处只处理异步操作enqueue
     */
    callBack.onLoadingBefore(request);

    mOkHttpClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            mHandler.post(() -> callBack.onFailure(request, e));

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                mHandler.post(() -> callBack.onSuccess(response));
            } else {
                mHandler.post(() -> callBack.onError(response));
            }
        }
    });


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

结束语

此工具类还没有完善,下篇文章继续完善,待完善内容:返回Resonpse直接解析成javaBean返回。
  • 1

完整代码

public class OkHttpUtils { /** * 网络访问要求singleton */ private static OkHttpUtils instance; // 必须要用的okhttpclient实例,在构造器中实例化保证单一实例 private OkHttpClient mOkHttpClient; public static final MediaType JSON = MediaType. parse("application/json; charset=utf-8"); private Handler mHandler; private OkHttpUtils() { /** * okHttp3中超时方法移植到Builder中 */ mOkHttpClient = (new OkHttpClient()).newBuilder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); mHandler = new Handler(Looper.getMainLooper()); } public static OkHttpUtils getInstance() { if (instance == null) { synchronized (OkHttpUtils.class) { if (instance == null) { instance = new OkHttpUtils(); } } } return instance; } /** * 对外提供的Get方法访问 * @param url * @param callBack */ public void Get(String url, MyCallBack callBack) { /** * 通过url和GET方式构建Request */ Request request = bulidRequestForGet(url); /** * 请求网络的逻辑 */ requestNetWork(request, callBack); } /** * 对外提供的Post方法访问 * @param url * @param parms: 提交内容为表单数据 * @param callBack */ public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) { /** * 通过url和POST方式构建Request */ Request request = bulidRequestForPostByForm(url, parms); /** * 请求网络的逻辑 */ requestNetWork(request, callBack); } /** * 对外提供的Post方法访问 * @param url * @param json: 提交内容为json数据 * @param callBack */ public void PostWithJson(String url, String json, MyCallBack callBack) { /** * 通过url和POST方式构建Request */ Request request = bulidRequestForPostByJson(url, json); /** * 请求网络的逻辑 */ requestNetWork(request, callBack); } /** * POST方式构建Request {json} * @param url * @param json * @return */ private Request bulidRequestForPostByJson(String url, String json) { RequestBody body = RequestBody.create(JSON, json); return new Request.Builder() .url(url) .post(body) .build(); } /** * POST方式构建Request {Form} * @param url * @param parms * @return */ private Request bulidRequestForPostByForm(String url, Map<String, String> parms) { FormBody.Builder builder = new FormBody.Builder(); if (parms != null) { for (Map.Entry<String, String> entry : parms.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } } FormBody body = builder.build(); return new Request.Builder() .url(url) .post(body) .build(); } /** * GET方式构建Request * @param url * @return */ private Request bulidRequestForGet(String url) { return new Request.Builder() .url(url) .get() .build(); } private void requestNetWork(Request request, MyCallBack callBack) { /** * 处理连网逻辑,此处只处理异步操作enqueue */ callBack.onLoadingBefore(request); mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { mHandler.post(() -> callBack.onFailure(request, e)); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { mHandler.post(() -> callBack.onSuccess(response)); } else { mHandler.post(() -> callBack.onError(response)); } } }); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178

定义的接口的完整代码

interface MyCallBack {

    void onLoadingBefore(Request request); void onSuccess(Response response); void onFailure(Request request, Exception e); void onError(Response response); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11