| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- 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;
- /**
- * <p>类说明</p>
- *
- * @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<ResponseBody> mCall;
- private static final Map<String, Call> 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<String, String> 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<ResponseBody>() {
- @Override
- public void onResponse(Call<ResponseBody> call, Response<ResponseBody> 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<ResponseBody> 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<String> 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<String, String> 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 <T> 解析类
- */
- public <T> Builder bodyType(@DataType.Type int bodyType, @NonNull Class<T> 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;
- }
- }
- }
|