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

前言:

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

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

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也只会走一次,必定也是单实例的。

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

既然是工具类,肯定要更加简单,此处我们需要提供针对GET和POST两种方式的访问方法。
1.工具类为GET访问方式提供的方法
 /**
 * 对外提供的Get方法访问
 * @param url
 * @param callBack
 */
public void Get(String url, MyCallBack callBack) {
    /**
     * 通过url和GET方式构建Request
     */
    Request request = bulidRequestForGet(url);
    /**
     * 请求网络的逻辑
     */
    requestNetWork(request, callBack);
}
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);

}
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);

}

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

构建Request对象

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

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

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

    return new Request.Builder()
            .url(url)
            .get()
            .build();
}

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();
}

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();
}
开始处理联网逻辑
上述代码及分析基本上把简单封装的东西讲完了,有了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);
            }
        }
    });


}
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);

}

封装进阶

看到此处,觉得封装已经完结了,不不不,还有一个重要的问题,不处理的话会导致崩溃的,这个问题就是,我们定义接口回调的地方是在子线程,而我们的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));
            }
        }
    });


}
结束语
此工具类还没有完善,下篇文章继续完善,待完善内容:返回Resonpse直接解析成javaBean返回。
完整代码
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));
                }
            }
        });


    }


}

定义的接口的完整代码

interface MyCallBack {

    void onLoadingBefore(Request request);

    void onSuccess(Response response);

    void onFailure(Request request, Exception e);

    void onError(Response response);

}
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值