美文网首页
Android之Okhttp的封装

Android之Okhttp的封装

作者: Android绝世小菜鸟 | 来源:发表于2017-01-02 23:50 被阅读0次

    最近需要用到网络请求,用到了Okhttp这个强大的库,写个小博客来做个笔记 先看一下Okhttp3和之前版本的不同之处。

    1.Okhttp3和OkHttp的对比

    • OkHttpClient创建方式不同

    例如:

    OkHttpClient.Builder okHttpClientBuilder = client.newBuilder(); 
            /* 超时设置 */  
            okHttpClientBuilder.connectTimeout(10, TimeUnit.SECONDS) 
                                .writeTimeout(30, TimeUnit.SECONDS) 
                                .readTimeout(30, TimeUnit.SECONDS);
    OkHttpClient mOkHttpClient = okHttpClientBuilder.build();
    

    okhttp直接newOkHttpClient,而okhttp3中提供了Builder,很好的使用了创建者设计模式 有以下参数:

    Dispatcher dispatcher; // 分发
    Proxy proxy; // 代理
    List<Protocol> protocols;
    List<ConnectionSpec> connectionSpecs;
    final List<Interceptor> interceptors = new ArrayList<>(); // 拦截器 final List<Interceptor> networkInterceptors = new ArrayList<>(); // 网络拦截器 ProxySelector proxySelector;
    CookieJar cookieJar;
    Cache cache; // 缓存
    InternalCache internalCache;
    SocketFactory socketFactory;
    SSLSocketFactory sslSocketFactory;
    HostnameVerifier hostnameVerifier;
    CertificatePinner certificatePinner;
    Authenticator proxyAuthenticator; // 代理证书
    Authenticator authenticator; // 证书
    ConnectionPool connectionPool;
    Dns dns; // DNS
    boolean followSslRedirects;
    boolean followRedirects;
    boolean retryOnConnectionFailure;
    int connectTimeout;
    int readTimeout;
    int writeTimeout;
    
    • cookie的设置方式不同:

    okhttp调用OkHttpClient的setCookieHandler方法,CookieHandler是Android SDK提供的标注的cookie管理,CookieHandler 的之类CookieManager实现了cookie的具体管理方法,构建CookieManager需要实现CookieStore接口,系统提供了一个默认的实现CookieStoreImpl,只负责把cookie存储在内存中。

    • post消息体构建方式不同

    okhttp使用MultipartBuilder,FormEncodingBuilder构建post消息体,最终构建出来的都是RequestBody,而okhttp3增加了RequestBody的子类,构造器放到了RequestBody的子类中,MultipartBody.Builder既可以添加表单数据,也可以添加文件等二进制数据

    • Call和Callback不同

    okhttp3 之前用CookieHandler管理cookie

    /* cookie管理 */ 
     mCookieHandler = new CookieManager(null, CookiePolicy.ACCEPT_ALL); 
     mOkHttpClient.setCookieHandler(mCookieHandler);
    

    3.0 之后新增了两个类Cookiejar、Cookie两个类,开放接口,需要用户自己去实现cookie的配管理。用户可以直接在CookieJar中简单设置Cookie的管理,如下:

    okHttpClientBuilder.cookieJar(new CookieJar() {
           private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
                 @Override
                   public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                     cookieStore.put(url, cookies);
                    }
    
                @Override
                  public List<Cookie> loadForRequest(HttpUrl url) {
                       List<Cookie> cookies = cookieStore.get(url);
                       return cookies != null ? cookies : new ArrayList<Cookie>();
                }
        });
    
    • OkHttpClient的Cancel方法去掉

    3.0之前我们去掉call 可以直接使用mOkHttpClient.cancel(tag);3.0之后直接阉割掉此方法我们可以采用如下方法:

     public void cancelCallsWithTag(Object tag) {
            checkInit();
    
            if (tag == null) {
                return;
            }
    
            synchronized (mOkHttpClient.dispatcher().getClass()) {
                for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
                    if (tag.equals(call.request().tag())) call.cancel();
                }
    
                for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
                    if (tag.equals(call.request().tag())) call.cancel();
                }
            }
        }
    

    2.Okhttp参数的构造

    public class Params {
        public static final String METHOD_GET = "get";
        public static final String METHOD_POST = "post";
        //3个构造参数 一般参数 file head
        private HashMap<String, Object> urlParams = new HashMap<>();
        private HashMap<String, File> fileParams = new HashMap<>();
        private HashMap<String, String> headers = new HashMap<>();
    
        private String api = "";
        private String baseUrl = "";
        private String method;
    
        public Params() {
            urlParams = new HashMap<String, Object>();
            fileParams = new HashMap<String, File>();
            headers = new HashMap<String, String>();
            setBaseUrl(Constants.me().getHost());
    
            //统一添加请求头
            headers.put("Accept", "application/json");
            headers.put("Version", Constants.me().getVersionName());
            headers.put("Gis-Lat", String.valueOf(Constants.me().getLatitude()));
            headers.put("Gis-Lng", String.valueOf(Constants.me().getLongitude()));
    
            String token = Constants.me().getToken();
            if (!TextUtils.isEmpty(token)) {
                headers.put("Authorization", "Bearer " + token);
            }
            setMethod(METHOD_POST);
        }
    
        public String getMethod() {
            return method;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public String getApi() {
            return api;
        }
    
        public void setApi(String api) {
            this.api = api;
        }
    
        public String getUrl() {
            return baseUrl + api;
        }
    
        public String getBaseUrl() {
            return baseUrl;
        }
    
        public void setBaseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
        }
    
    
    
        public void put(String key, Object value) {
            if (key != null) {
                urlParams.put(key, value);
            }
        }
        public void put(String key, String value) {
            if (key != null) {
                urlParams.put(key, value);
            }
        }
    
        public void put(String key, int value) {
            if (key != null) {
                urlParams.put(key, String.valueOf(value));
            }
        }
    
        public void put(String key, double value) {
            if (key != null) {
                urlParams.put(key, String.valueOf(value));
            }
        }
        public void put(String key, float value) {
            if (key != null) {
                urlParams.put(key, String.valueOf(value));
            }
        }
    
        public void putHeaders(final String key, final int value) {
            this.putHeaders(key, String.valueOf(value));
        }
    
        public void putHeaders(final String key, final String value) {
            headers.put(key, value);
        }
    
        /**
         * @param key
         * @param file
         */
        public void put(String key, File file) {
            if (file != null && file.exists()) {
                fileParams.put(key, file);
            }
        }
        //是否为文件
        public boolean isMultipart() {
            return !fileParams.isEmpty();
        }
    
    
        public HashMap<String, Object> getUrlParams() {
            return urlParams;
        }
    
        public HashMap<String, File> getFileParams() {
            return fileParams;
        }
    
        public HashMap<String, String> getHeaders() {
            return headers;
        }
    
        @Override
        public String toString() {
            return urlParams.toString();
        }
    }
    
    

    3.Okhttp的封装

    final public class HttpKit {
        private static final int DEFAULT_MILLISECONDS = 60000; //默认的超时时间
    
        private OkHttpClient.Builder okHttpClientBuilder;
        private OkHttpClient okHttpClient;
        private Handler mDelivery;
        private Context mContext;
        private final List<ResponseHandler> handlers = new ArrayList<>();//请求返回值处理
        private PersistentCookieStore cookieStore;//永久化保存cookie
    
        public interface HttpCallback<T> {
            //开始的时候调用,子类可选择实现
            public void onStarted(Request request);
            //当进度条改变的时候,子类可选择实现
            public void onProgressChanged(float progress, long total);
    
            /**
             * response是否正确
             *
             * @param response
             * @return
             */
            @Deprecated
            public boolean validateReponse(Response response);
            //解析数据,可选择实现,一般子类会自定义一个callback类,去解析
            public T parseNetworkResponse(Response response) throws ApiException;
            //子类回调,可选择实现
            public void onError(ApiException e);
            //子类回调
            public abstract void onResponse(T response);
        }
    
        private static final HttpKit me = new HttpKit();
    
    
        private HttpKit() {
            okHttpClientBuilder = new OkHttpClient.Builder();
            okHttpClientBuilder.connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
            okHttpClientBuilder.readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
            okHttpClientBuilder.writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
    
            mDelivery = new Handler(Looper.getMainLooper());
        }
    
        public static HttpKit me() {
            return me;
        }
    
        //当需要使用cookie的时候,调用
        public static HttpKit init(Context context) {
            me().setContext(context);
            return me();
        }
    
        private void setContext(Context context) {
            this.mContext = context;
            cookieStore = new PersistentCookieStore(mContext);//永久化保存cookie
            CookieJarImpl cookieJar = new CookieJarImpl(cookieStore);
            okHttpClientBuilder.cookieJar(cookieJar);
        }
        //设置cookie
        public void setCookie(Uri uri, Cookie cookie) {
            HttpUrl httpUrl = new HttpUrl.Builder().scheme(uri.getScheme()).host(uri.getHost()).build();
            cookieStore.add(httpUrl, cookie);
        }
    
        public void removeAllCookie() {
            cookieStore.removeAll();
        }
    
        //本地拦截器
        public HttpKit addInterceptor(Interceptor interceptor) {
            okHttpClientBuilder.addInterceptor(interceptor);
            return this;
        }
        //网络拦截器
        public HttpKit addNetworkInterceptor(Interceptor interceptor) {
            okHttpClientBuilder.addNetworkInterceptor(interceptor);
            return this;
        }
    
    
        public List<ResponseHandler> handlers() {
            return handlers;
        }
    
        public HttpKit addHandler(ResponseHandler handler) {
            handlers.add(handler);
            return this;
        }
    
        public Handler getDelivery() {
            return mDelivery;
        }
    
        public void build() {
            okHttpClient = okHttpClientBuilder.build();
        }
    
        private Request buildRequest(Params params) {
            Request.Builder builder = new Request.Builder();
            builder.url(params.getUrl());
            //头
            if (!params.getHeaders().isEmpty()) {
                for (Map.Entry<String, String> header : params.getHeaders().entrySet()) {
                    if (header.getKey() != null) {
                        builder.addHeader(header.getKey(), header.getValue());
                    }
                }
            }
            //文件表单上传
            if (params.isMultipart()) {
                MultipartBody.Builder body = new MultipartBody.Builder();
                body.setType(MultipartBody.FORM);
                //有url
                if (!params.getUrlParams().isEmpty()) {
                    for (Map.Entry<String, Object> param : params.getUrlParams().entrySet()) {
                        if (param.getKey() != null) {
                            body.addFormDataPart(param.getKey(), (String) param.getValue());
                        }
                    }
                }
                //有file对象
                for (Map.Entry<String, File> param : params.getFileParams().entrySet()) {
                    File file = param.getValue();
                    if (file != null && file.exists()) {
                        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
                        body.addFormDataPart(param.getKey(), file.getName(), fileBody);
                    }
                }
                builder.post(body.build());
                //不是表单,是一般的Post请求的话
            } else if (Params.METHOD_POST.equals(params.getMethod())) {
                FormBody.Builder body = new FormBody.Builder();
                body.add("i", CryptKit.encrypt(params.getUrlParams(), params.getUrl()));
                builder.post(body.build());
            }
            return builder.build();
        }
    
        //同步请求
        public Response execute(Params params) throws IOException {
            Request request = buildRequest(params);
    
            Call call = okHttpClient.newCall(request);
            return call.execute();
        }
    
        /**
         * get请求不做parseNetworkResponse处理,原数据返回
         *
         * @param params
         * @param callback
         */
        public void get(Params params, final HttpCallback callback) {
            Request request = buildRequest(params);
    
            if (callback != null) callback.onStarted(request);
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    sendFail(new ApiException(e), callback);
                }
    
                @Override
                public void onResponse(Call call, Response response) {
                    try {
                        if (call.isCanceled()) {
                            sendFail(new ApiException("取消", -1), callback);
                            return;
                        }
    
                        Object o = callback.parseNetworkResponse(response);
                        sendSuccess(o, callback);
                    } catch (ApiException e) {
                        sendFail(e, callback);
                    } finally {
                        if (response.body() != null)
                            response.body().close();
                    }
                }
            });
        }
    
        public void post(final Params params, final HttpCallback callback) {
            if (params == null || callback == null) {
                Log4a.e("post params null");
                return;
            }
            Request request = buildRequest(params);
    
            if (callback != null) callback.onStarted(request);
            Call call = okHttpClient.newCall(request);
            Log4a.e("======>post "+params.getUrl());
            Log4a.e("======>   params:"+params.toString());
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    sendFail(new ApiException(e.getCause()), callback);
                }
    
                @Override
                public void onResponse(Call call, Response response) {
                    try {
                        if (call.isCanceled()) {
                            sendFail(new ApiException("取消", -1), callback);
                            return;
                        }
    
                        Object o = callback.parseNetworkResponse(response);
                        sendSuccess(o, callback);
                    } catch (ApiException e) {
                        sendFail(e, callback);
                    } finally {
                        if (response.body() != null)
                            response.body().close();
                    }
                }
            });
        }
    
        private void sendFail(final ApiException e, final HttpCallback callback) {
            if (callback == null) return;
    
            mDelivery.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (callback != null) {
                            callback.onError(e);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        private void sendSuccess(final Object object, final HttpCallback callback) {
            if (callback == null) return;
    
            mDelivery.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (callback != null && object != null) {
                            callback.onResponse(object);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
    

    4.子类自定义CallBack方法执行相应的操作,例如解析数据等

    public abstract class JSONCallback<T> extends TypeToken<T> implements HttpKit.HttpCallback<T> {
    
        private Type mClass;//获取类似List<Student>或者 Student的type
    
        public JSONCallback() {
            mClass = getType();
        }
    
        public void onStarted(Request request) {
        }
    
        public void onProgressChanged(float progress, long total) {
    
        }
    
        /**
         * response是否正确
         *
         * @param response
         * @return
         */
        @Deprecated
        public boolean validateReponse(Response response) {
            return true;
        }
    
        public T parseNetworkResponse(Response response) throws ApiException {
            String resp = "";
            String data = "";
            int status;
            String message;
    
            try {
                resp = response.body().string();
                Log4a.e("======>> response:"+response.request().url().url());
                Log4a.json(resp);
            } catch (IOException e) {
                throw new ApiException(e);
            }
    
            try {
                JSONObject jsonObject = new JSONObject(resp);
                status = jsonObject.getInt("code");
                message = jsonObject.getString("message");
                if (status == 1000 && jsonObject.has("data")) {
                    data = jsonObject.getString("data");
                }
            } catch (JSONException e) {
                throw new ApiException(e);
            }
    
            List<ResponseHandler> handlers = HttpKit.me().handlers();
            if (handlers != null && handlers.size() > 0) {
                for (ResponseHandler handler : handlers)
                    handler.onHandler(status, message, response.request().url().url().getPath());
            }
    
            if (status != 1000) {
                throw new ApiException(message, status);
            }
    
            try {
                if (GsonKit.isSubObjectOf(mClass, List.class)) {
                    if ("".equals(data) || data == null||"{}".equals(data)) {
                        data = "[]";
                    }
                } else {
                    if ("".equals(data) || data == null||"[]".equals(data)) {
                        data = "{}";
                    }
                }
                return GsonKit.fromJson(data, mClass);
            } catch (Exception e) {
                throw new ApiException(message, status, e);
            }
        }
    
        public void onError(ApiException e) {
            if (e.getStatus() == 0)
                ViewKit.shortToast("联网失败,请检查网络");
            else if (e.getStatus() == -1) {// TODO: 2016/11/26
    
            } else if (!StringKit.isEmpty(e.getMessage()))
                ViewKit.shortToast(e.getMessage());
        }
    
        public abstract void onResponse(T response);
    }
    

    5.Cookie的一些设置

    //当需要使用cookie的时候,调用
        public static HttpKit init(Context context) {
            me().setContext(context);
            return me();
        }
    
        private void setContext(Context context) {
            this.mContext = context;
            cookieStore = new PersistentCookieStore(mContext);//永久化保存cookie
            CookieJarImpl cookieJar = new CookieJarImpl(cookieStore);
            okHttpClientBuilder.cookieJar(cookieJar);
        }
        //设置cookie
        public void setCookie(Uri uri, Cookie cookie) {
            HttpUrl httpUrl = new HttpUrl.Builder().scheme(uri.getScheme()).host(uri.getHost()).build();
            cookieStore.add(httpUrl, cookie);
        }
    
        public void removeAllCookie() {
            cookieStore.removeAll();
        }
    

    CookieJarImpl的实现,PersistentCookieStore的永久化代码,网上有,直接搜

    public class CookieJarImpl implements CookieJar {
        private CookieStore cookieStore;
    
        public CookieJarImpl(CookieStore cookieStore) {
            if (cookieStore == null)
                throw new IllegalArgumentException(String.format("cookieStore can not be null."));
            this.cookieStore = cookieStore;
        }
    
        @Override
        public synchronized void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            cookieStore.add(url, cookies);
        }
    
        @Override
        public synchronized List<Cookie> loadForRequest(HttpUrl url) {
            return cookieStore.get(url);
        }
    
        public CookieStore getCookieStore() {
            return cookieStore;
        }
    }
    

    相关文章

      网友评论

          本文标题:Android之Okhttp的封装

          本文链接:https://www.haomeiwen.com/subject/nxfgvttx.html