Android

Android OKHttp3 二次封装网络框架

2020-02-26  本文已影响0人  极客匠

简介:OKHttp是一个Android当前最火的处理网络请求第三方框架库,由移动支付Square公司开源贡献的。用于替代HttpUrlConnection和Apache HttpClient(android API23 6.0里已移除HttpClient)。

封装

首先看一下OKHttp的使用

private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
               .readTimeout(30, TimeUnit.SECONDS)
               .addInterceptor(new LoggingInterceptor())
               .cache(new Cache(context.getExternalFilesDir("okhttp"),cacheSize)).build();


    public static void getRequest(String url, final ResultListener<Object> listener) {
        Request request = new Request.Builder().url(url).method("GET", null).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (null != listener) {
                    listener.onFailure(e.getMessage());
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (null != listener) {
                    listener.onSuccess(response);
                }
            }
        });
    }

这种封装成工具类的比完全没有封装的好了很多,但是还是存在一定的问题的。封装成工具类的话,别人完全有权限访问你这个工具类,他可以随时修改你工具类里面的实现,这给维护带来了一定的成本。

再此之前,我们要先了解网络请求哪些参数是必要的,哪些是非必要的

了解完必要参数和非必要参数之后,我们就将采用建造者模式,把非必要的参数都提取封装在ManbaOkhttpOption当中。代码如下:

public class ManbaOkhttpOption {
    private String mUrl;
    private String mTag;
    private Map<String, String> mHeaders;

    public ManbaOkhttpOption(String mTag) {
        this.mTag = mTag;
    }

    public String getTag() {
        return mTag;
    }

    public Map<String, String> getHeaders() {
        return mHeaders;
    }

    public static final class Builder {
        public String mTag;
        public Map<String, String> mHeaders;
        public String mUrl;

        public Builder setTag(String mTag) {
            this.mTag = mTag;
            return this;
        }

        public Builder setHeaders(Map<String, String> mHeaders) {
            this.mHeaders = mHeaders;
            return this;
        }

        public Builder setUrl(String mUrl) {
            this.mUrl = mUrl;
            return this;
        }

        public ManbaOkhttpOption build() {
            ManbaOkhttpOption option = new ManbaOkhttpOption(mTag);
            option.mHeaders = mHeaders;
            option.mUrl = mUrl;
            return option;
        }
    }

}

建造者模式的优点:

- 封装性很好,将产品本身与产品的创建过程解耦,对外屏蔽了对象的构建过程
- 扩展性强,如果有新的需求,只需要增加新的具体建造者,无须修改原有类库的代码

这样封装实现出来的接口IManbaRequest:

public interface IManbaRequest {
    void init(Context context);

    void doGet(String url, IResponseCallback callback);

    void doGet(String url, Map<String, String> paramsMap, IResponseCallback callback);

    void doGet(String url, Map<String, String> paramsMap, ManbaOkhttpOption option, IResponseCallback callback);

    void doPost(String url, Map<String, String> paramsMap, IResponseCallback callback);

    void doPost(String url, Map<String, String> paramsMap, ManbaOkhttpOption option, IResponseCallback callback);

    void cancel(String tag);
}

可以看到,我们有几个方法:

ManbaOkhttpRequest实现

OkHttp 的配置是非常灵活的,这样我们主要看一下怎么配置请求头,请求参数,以及怎样取消网络请求。

package com.sunhdj.manbaokhttp;

import android.content.Context;
import android.os.Handler;

import com.sunhdj.manbaokhttp.utils.NetUtils;

import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * huangdaju
 * 2020-02-25
 **/

public class ManbaOkhttpRequest implements IManbaRequest {

    private static int cacheSize = 10 * 1024 * 1024; // 10 MiB

    private static OkHttpClient client;
    private Context mContext;

    public static Handler mHandler = new Handler();

    public static Handler getHandler() {
        if (mHandler == null) {
            mHandler = new Handler();
        }
        return mHandler;
    }

    private volatile static ManbaOkhttpRequest instance = null;

    private ManbaOkhttpRequest() {
    }


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

    @Override
    public void init(Context context) {
        mContext = context.getApplicationContext();
        client = getCilent();
    }

    private OkHttpClient getCilent() {
        if (client == null) {
            OkHttpClient.Builder mBuilder = new OkHttpClient.Builder().
                    connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .addInterceptor(new LoggingInterceptor())
                    .cache(new Cache(mContext.getExternalFilesDir("manbaOkhttp"), cacheSize));
            client = mBuilder.build();
        }
        return client;

    }

    @Override
    public void doGet(String url, IResponseCallback callback) {
        doGet(url, null, null, callback);
    }

    @Override
    public void doGet(String url, Map<String, String> paramsMap, IResponseCallback callback) {
        doGet(url, paramsMap, null, callback);
    }

    @Override
    public void doGet(String url, Map<String, String> paramsMap, ManbaOkhttpOption option, final IResponseCallback callback) {

        url = NetUtils.appendUrl(url, paramsMap);
        final ManbaOkhttpOption manbaOkhttpOption = NetUtils.checkNetworkOption(option, url);
        Request.Builder builder = new Request.Builder().url(url).tag(manbaOkhttpOption.getTag());
        builder = configHeaders(builder, manbaOkhttpOption);

        Request build = builder.build();

        getCilent().newCall(build).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handleError(e, callback);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                handleResult(response, callback);
            }
        });
    }

    @Override
    public void doPost(String url, Map<String, String> paramsMap, IResponseCallback callback) {
        doPost(url,paramsMap,null,callback);
    }

    @Override
    public void doPost(String url, Map<String, String> paramsMap, ManbaOkhttpOption option, final IResponseCallback callback) {
        url = NetUtils.appendUrl(url, paramsMap);
        final ManbaOkhttpOption manbaOkhttpOption = NetUtils.checkNetworkOption(option, url);
        // 以表单的形式提交
        FormBody.Builder builder = new FormBody.Builder();
        builder=configPostParam(builder,paramsMap);
        FormBody formBody = builder.build();

        Request.Builder requestBuilder = new Request.Builder().url(url).post(formBody).tag(manbaOkhttpOption.getTag());
        requestBuilder = configHeaders(requestBuilder, manbaOkhttpOption);

        Request build = requestBuilder.build();

        getCilent().newCall(build).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handleError(e, callback);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                handleResult(response, callback);
            }
        });
    }

    private FormBody.Builder configPostParam(FormBody.Builder builder, Map<String, String> paramsMap) {
        if(paramsMap!=null){
            Set<Map.Entry<String, String>> entries = paramsMap.entrySet();
            for(Map.Entry<String,String> entry:entries ){
                String key = entry.getKey();
                String value = entry.getValue();
                builder.add(key,value);
            }
        }
        return builder;
    }

    private Request.Builder configHeaders(Request.Builder builder, ManbaOkhttpOption option) {
        Map<String, String> headers = option.getHeaders();
        if (headers == null || headers.size() == 0) {
            return builder;
        }
        Set<Map.Entry<String, String>> entries = headers.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            builder.addHeader(key, value);
        }
        return builder;

    }


    private void handleResult(Response response, final IResponseCallback callback) throws IOException {
        final String result = response.body().string();
        if (callback != null) {
            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onResponse(result);
                }
            });
        }
    }

    private void handleError(IOException e, final IResponseCallback callback) {
        if (callback != null) {
            final ManbaOkHttpException httpException = new ManbaOkHttpException();
            httpException.e = e;
            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onFail(httpException);
                }
            });

        }
    }

    @Override
    public void cancel(String tag) {
        if (client != null) {
            for (Call call : client.dispatcher().queuedCalls()) {
                if (call.request().tag().equals(tag)) {
                    call.cancel();
                }
            }
        }
    }
}

ManbaOkhttpRequest的实现其实很简单,主要根据ManbaOkhttpOption做相应的配置。如果不熟悉okhttp的request用法,请参考博客OkHttp使用完全教程

每天多努力那么一点点,积少成多

上一篇下一篇

猜你喜欢

热点阅读