package com.guiying.common.http; import android.support.annotation.NonNull; import android.text.TextUtils; import com.franmontiel.persistentcookiejar.ClearableCookieJar; import com.franmontiel.persistentcookiejar.PersistentCookieJar; import com.franmontiel.persistentcookiejar.cache.SetCookieCache; import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; import com.guiying.common.R; import com.guiying.common.utils.NetworkUtils; import com.guiying.common.utils.StringUtils; import com.guiying.common.utils.ToastUtils; import com.guiying.common.utils.Utils; import com.orhanobut.logger.Logger; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; /** *

类说明

* * @author 张华洋 2016/12/5 14:09 * @version V1.0.0 * @name HttpClient */ public class HttpClient { /*The certificate's password*/ private static final String STORE_PASS = "6666666"; private static final String STORE_ALIAS = "666666"; /*用户设置的BASE_URL*/ private static String BASE_URL = ""; /*本地使用的baseUrl*/ private String baseUrl = ""; private static OkHttpClient okHttpClient; private Builder mBuilder; private Retrofit retrofit; private Call mCall; private static final Map CALL_MAP = new HashMap<>(); /** * 获取HttpClient的单例 * * @return HttpClient的唯一对象 */ private static HttpClient getIns() { return HttpClientHolder.sInstance; } /** * 单例模式中的静态内部类写法 */ private static class HttpClientHolder { private static final HttpClient sInstance = new HttpClient(); } private HttpClient() { ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(Utils.getContext())); //HttpsUtil.SSLParams sslParams = HttpsUtil.getSslSocketFactory(Utils.getContext(), R.raw.cer,STORE_PASS , STORE_ALIAS); okHttpClient = new OkHttpClient.Builder() .connectTimeout(10000L, TimeUnit.MILLISECONDS) //.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) // .hostnameVerifier(HttpsUtil.getHostnameVerifier()) .addInterceptor(new LoggerInterceptor(null, true)) .cookieJar(cookieJar) .build(); } public Builder getBuilder() { return mBuilder; } private void setBuilder(Builder builder) { this.mBuilder = builder; } /** * 获取的Retrofit的实例, * 引起Retrofit变化的因素只有静态变量BASE_URL的改变。 */ private void getRetrofit() { if (!BASE_URL.equals(baseUrl) || retrofit == null) { baseUrl = BASE_URL; retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .client(okHttpClient) .build(); } } public void post(final OnResultListener onResultListener) { Builder builder = mBuilder; mCall = retrofit.create(ApiService.class) .executePost(builder.url, builder.params); putCall(builder, mCall); request(builder, onResultListener); } public void get(final OnResultListener onResultListener) { Builder builder = mBuilder; if (!builder.params.isEmpty()) { String value = ""; for (Map.Entry entry : builder.params.entrySet()) { String mapKey = entry.getKey(); String mapValue = entry.getValue(); String span = value.equals("") ? "" : "&"; String part = StringUtils.buffer(span, mapKey, "=", mapValue); value = StringUtils.buffer(value, part); } builder.url(StringUtils.buffer(builder.url, "?", value)); } mCall = retrofit.create(ApiService.class).executeGet(builder.url); putCall(builder, mCall); request(builder, onResultListener); } private void request(final Builder builder, final OnResultListener onResultListener) { if (!NetworkUtils.isConnected()) { ToastUtils.showLongToastSafe(R.string.current_internet_invalid); onResultListener.onFailure(Utils.getString(R.string.current_internet_invalid)); return; } mCall.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { if (200 == response.code()) { try { String result = response.body().string(); parseData(result, builder.clazz, builder.bodyType, onResultListener); } catch (IOException e) { e.printStackTrace(); } } if (!response.isSuccessful() || 200 != response.code()) { onResultListener.onError(response.code(), response.message()); } if (null != builder.tag) { removeCall(builder.url); } } @Override public void onFailure(Call call, Throwable t) { t.printStackTrace(); onResultListener.onFailure(t.getMessage()); if (null != builder.tag) { removeCall(builder.url); } } }); } /** * 添加某个请求 */ private synchronized void putCall(Builder builder, Call call) { if (builder.tag == null) return; synchronized (CALL_MAP) { CALL_MAP.put(builder.tag.toString() + builder.url, call); } } /** * 取消某个界面都所有请求,或者是取消某个tag的所有请求; * 如果要取消某个tag单独请求,tag需要传入tag+url * * @param tag 请求标签 */ public synchronized void cancel(Object tag) { if (tag == null) return; List list = new ArrayList<>(); synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.startsWith(tag.toString())) { CALL_MAP.get(key).cancel(); list.add(key); } } } for (String s : list) { removeCall(s); } } /** * 移除某个请求 * * @param url 添加的url */ private synchronized void removeCall(String url) { synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.contains(url)) { url = key; break; } } CALL_MAP.remove(url); } } /** * Build a new HttpClient. * url is required before calling. All other methods are optional. */ public static final class Builder { private String builderBaseUrl = ""; private String url; private Object tag; private Map params = new HashMap<>(); /*返回数据的类型,默认是string类型*/ @DataType.Type private int bodyType = DataType.STRING; /*解析类*/ private Class clazz; public Builder() { } /** * 请求地址的baseUrl,最后会被赋值给HttpClient的静态变量BASE_URL; * * @param baseUrl 请求地址的baseUrl */ public Builder baseUrl(String baseUrl) { this.builderBaseUrl = baseUrl; return this; } /** * 除baseUrl以外的部分, * 例如:"mobile/login" * * @param url path路径 */ public Builder url(String url) { this.url = url; return this; } /** * 给当前网络请求添加标签,用于取消这个网络请求 * * @param tag 标签 */ public Builder tag(Object tag) { this.tag = tag; return this; } /** * 添加请求参数 * * @param key 键 * @param value 值 */ public Builder params(String key, String value) { this.params.put(key, value); return this; } /** * 响应体类型设置,如果要响应体类型为STRING,请不要使用这个方法 * * @param bodyType 响应体类型,分别:STRING,JSON_OBJECT,JSON_ARRAY,XML * @param clazz 指定的解析类 * @param 解析类 */ public Builder bodyType(@DataType.Type int bodyType, @NonNull Class clazz) { this.bodyType = bodyType; this.clazz = clazz; return this; } public HttpClient build() { if (!TextUtils.isEmpty(builderBaseUrl)) { BASE_URL = builderBaseUrl; } HttpClient client = HttpClient.getIns(); client.getRetrofit(); client.setBuilder(this); return client; } } /** * 数据解析方法 * * @param data 要解析的数据 * @param clazz 解析类 * @param bodyType 解析数据类型 * @param onResultListener 回调方数据接口 */ @SuppressWarnings("unchecked") private void parseData(String data, Class clazz, @DataType.Type int bodyType, OnResultListener onResultListener) { switch (bodyType) { case DataType.STRING: onResultListener.onSuccess(data); break; case DataType.JSON_OBJECT: onResultListener.onSuccess(DataParseUtil.parseObject(data, clazz)); break; case DataType.JSON_ARRAY: onResultListener.onSuccess(DataParseUtil.parseToArrayList(data, clazz)); break; case DataType.XML: onResultListener.onSuccess(DataParseUtil.parseXml(data, clazz)); break; default: Logger.e("http parse tip:", "if you want return object, please use bodyType() set data type"); break; } } }