网络请求工具类

网络请求相关类,基于Retrofit

def retrofit_version = "2.4.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version"
implementation "com.squareup.retrofit2:adapter-rxjava:$retrofit_version"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"

目录结构如下:
network
├─ api
│  └─ ApiServices
├─ coverter
│  ├─ CustomGsonCoverterFactory
│  ├─ CustomGsonRequestBodyConverter
│  └─ CustomGsonResponseBodyConverter
├─ interceptor
│  └─ HTTPInterceptor
├─ livedata
│  ├─ LiveDataCallAdapter
│  └─ LiveDataCallAdapterFactory
├─ result
│  ├─ BaseData
│  ├─ ResponseData
│  └─ Status
├─ CookieManager
├─ Http
└─ RetrofitUtils


ApiServices api类

/**
 * @author fada
 * @date 18-3-8
 * api
 */
public interface ApiServices {

}

coverter,自定义的工厂类,用于拦截返回结果,进行统一处理
CustomGsonCoverterFactory

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

/**
 * @author : fada
 * Date : 2018/5/5
 * Description : input your description
 */
public class CustomGsonCoverterFactory extends Converter.Factory {
    private final Gson gson;

    private CustomGsonCoverterFactory(Gson gson) {
        this.gson = gson;
    }

    public static CustomGsonCoverterFactory create() {
        return create(new Gson());
    }

    public static CustomGsonCoverterFactory create(Gson gson) {
        if (gson == null) {
            throw new NullPointerException("gson == null");
        }
        return new CustomGsonCoverterFactory(gson);
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new CustomGsonResponseBodyConverter<>(gson, type);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations,
                                                          Annotation[] methodAnnotations,
                                                          Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new CustomGsonRequestBodyConverter<>(gson, adapter);
    }
}

CustomGsonRequestBodyConverter

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;

import cn.mofada.hellonavigation.utils.LogUtils;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;

/**
 * @author : fada
 * Date : 2018/5/5
 * Description : input your description
 */
public class CustomGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    private final Gson gson;
    private final TypeAdapter<T> adapter;

    CustomGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }

    @Override
    public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        LogUtils.d("CustomGsonRequestBodyConverter ( convert ) : [ " + jsonWriter.toString() + " ] ");
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

CustomGsonResponseBodyConverter

import com.google.gson.Gson;

import java.io.IOException;
import java.lang.reflect.Type;

import cn.mofada.hellonavigation.utils.LogUtils;
import okhttp3.ResponseBody;
import retrofit2.Converter;

/**
 * @author : fada
 * Date : 2018/5/5
 * Description : input your description
 */
public class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private static final String TAG = "CustomGsonResponseBodyC";

    private final Gson gson;

    private final Type type;

    CustomGsonResponseBodyConverter(Gson gson, Type type) {
        this.gson = gson;
        this.type = type;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
        //在这里进行拦截操作
        String response = value.string();
        LogUtils.d("CustomGsonResponseBodyConverter called with: response : [ " + response + "" +
                " ] ");
        //        BaseData baseData = gson.fromJson(response, BaseData.class);
        return gson.fromJson(response, type);
    }


}


interceptor,拦截器,打印请求信息

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import cn.mofada.hellonavigation.utils.LogUtils;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * @author : www10
 * Date : 2018/7/21
 * Description : 请求拦截器
 */
public class HTTPInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        logRequest(request);
        return chain.proceed(request);
    }

    /**
     * 打印请求的信息
     *
     * @param request
     */
    private void logRequest(Request request) {
        String method = request.method();
        if ("GET".equals(method)) {
            //get请求
            doGet(request);
        } else if ("POST".equals(method)) {
            //post请求
            doPost(request);
        }
    }

    /**
     * get请求
     *
     * @param request
     */
    private void doGet(Request request) {
        Map<String, Object> params = new LinkedHashMap<>();

        HttpUrl url = request.url();
        Set<String> names = url.queryParameterNames();

        params.put("url", url.url().toString());
        for (String name : names) {
            params.put(name, url.queryParameterValues(name));
        }
        logParams(params);
    }

    /**
     * 处理post
     *
     * @param request
     */
    private void doPost(Request request) {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("url", request.url().url().toString());

        FormBody body = null;
        try {
            body = (FormBody) request.body();
            for (int i = 0; i < body.size(); i++) {
                params.put(body.encodedName(i), body.encodedValue(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        logParams(params);
    }

    /**
     * 打印参数
     *
     * @param params
     */
    private void logParams(Map<String, Object> params) {
        LogUtils.d( "HTTPInterceptor called with: params = [" + params + "]");
    }
}


livedata,LiveData请求转换器,适配器
LiveDataCallAdapter

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;

import java.lang.reflect.Type;

import cn.mofada.hellonavigation.network.result.ResponseData;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * @author fada
 * @date 18-3-8
 */
public class LiveDataCallAdapter<R> implements CallAdapter<R, LiveData<ResponseData<Object>>> {
    private final Type responseType;

    public LiveDataCallAdapter(Type responseType) {
        this.responseType = responseType;
    }

    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public LiveData<ResponseData<Object>> adapt(final Call call) {
        final MutableLiveData<ResponseData<Object>> liveData = new MutableLiveData<>();
        liveData.postValue(ResponseData.loading());
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                liveData.postValue(ResponseData.success(response.body()));
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                liveData.postValue(ResponseData.error(t.getMessage()));
            }
        });
        return liveData;
    }
}

LiveDataCallAdapterFactory

import android.arch.lifecycle.LiveData;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import cn.mofada.hellonavigation.network.result.ResponseData;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;

/**
 * @author fada
 * @date 18-3-8
 */
public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
    public static LiveDataCallAdapterFactory create() {
        return new LiveDataCallAdapterFactory();
    }

    private LiveDataCallAdapterFactory() {
    }

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        //获取类型是否是livedata类型
        // LiveData<ResponseData<*Gson>>
        if (getRawType(returnType) != LiveData.class) {
            return null;
        }
        //获取返回的类型 ResponseData<*Gson>
        Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);

        //判断外层是否是ResponseData,如果是则继续获取
        if (getRawType(observableType) == ResponseData.class) {
            // 获取最内层type
            // *Gson
            observableType = getParameterUpperBound(0, (ParameterizedType) observableType);
        }else{
            throw new IllegalStateException("Response must be like"
                    + " LiveData<ResponseData<*Gson>>");
        }

        return new LiveDataCallAdapter<>(observableType);
    }
}


result,请求结果封装类
BaseData

/**
 * @author : fada
 *         Date : 2018/4/27
 *         Description : input your description
 */
public class BaseData<T> {
    private String message;
    private int code;
    private int count;
    private long currentTime;
    private T data;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public long getCurrentTime() {
        return currentTime;
    }

    public void setCurrentTime(long currentTime) {
        this.currentTime = currentTime;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getMessage() {
        return message == null ? "--" : message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "BaseData{" +
                "message='" + message + '\'' +
                ", code=" + code +
                ", data=" + data +
                '}';
    }
}

ResponseData

/**
 * @author fada
 * @date 18-3-8
 */
public class ResponseData<T> {
    private Status code;
    private T data;
    private String msg;

    private ResponseData(Status code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "ResponseData{" +
                "code=" + code +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }

    public Status getCode() {
        return code;
    }

    public T getData() {
        return data;
    }

    public String getMsg() {
        return msg;
    }

    public static <T> ResponseData<T> success(T data) {
        return new ResponseData<>(Status.SUCCESS, data, "");
    }

    public static <T> ResponseData<T> loading() {
        return new ResponseData<>(Status.LOADING, null, "");
    }

    public static <T> ResponseData<T> error(String msg) {
        return new ResponseData<>(Status.ERROR, null, msg);
    }
}

Status

package cn.mofada.hellonavigation.network.result;

/**
 * @author fada
 * @date 18-3-8
 */
public enum Status {
    /**
    请求成功
     */
    SUCCESS,
    /**
     * 加载中
     */
    LOADING,
    /**
     * 错误
     */
    ERROR
}


CookieManager,会话保持类

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;

/**
 * @author fada
 * @date 18-2-26
 * cookie回话保持类
 */
class CookieManager implements CookieJar {
    private HashMap<String, List<Cookie>> cookies = new HashMap<>();

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        this.cookies.put(url.host(), cookies);
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        return this.cookies.get(url.host()) == null ? new ArrayList<Cookie>() : this.cookies.get
                (url.host());
    }
}


Http,地址类

package cn.mofada.hellonavigation.network;

/**
 * @author fada
 * @date 18-2-26
 * 接口地址
 */
public class Http {
    /**
     * 项目正式地址
     */
    public static final String HTTP = "http://www.mofada.cn";
}

RetrofitUtils

import java.util.concurrent.TimeUnit;

import cn.mofada.hellonavigation.network.livedata.LiveDataCallAdapterFactory;
import cn.mofada.hellonavigation.network.api.ApiServices;
import cn.mofada.hellonavigation.network.coverter.CustomGsonCoverterFactory;
import cn.mofada.hellonavigation.network.interceptor.HTTPInterceptor;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * @author fada
 * @date 18-2-26
 * retrofit 工具类
 */
public class RetrofitUtils {

    /**
     * 连接超时时间,单位s
     */
    private static final int CONNECT_TIME_OUT = 10;

    /**
     * 读取超时时间,单位s
     */
    private static final int READ_TIME_OUT = 10;

    /**
     * 写入超时时间,单位s
     */
    private static final int WRITE_TIME_OUT = 10;

    /**
     * 工具类单例
     */
    private static volatile RetrofitUtils sInstance;

    /**
     * retrofit实例
     */
    private final Retrofit mRetrofit;

    /**
     * 私有构造函数,进行单例模式,在初始化中进行retrofit的初始话
     */
    private RetrofitUtils() {
        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                //设置超时
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)
                //设置会话保持
                .cookieJar(new CookieManager())
                .addInterceptor(new HTTPInterceptor())
                .build();
        mRetrofit = new Retrofit
                .Builder()
                .baseUrl(Http.HTTP)
                .client(okHttpClient)
                //添加gson转换器
                .addConverterFactory(CustomGsonCoverterFactory.create())
                //添加字符串转化器
                .addConverterFactory(ScalarsConverterFactory.create())
                //rxjava2转换器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                //livedata转换器
                .addCallAdapterFactory(LiveDataCallAdapterFactory.create())
                .build();
    }

    /**
     * 获取api服务
     *
     * @return 返回服务接口类
     */
    public ApiServices getServerices() {
        return mRetrofit.create(ApiServices.class);
    }

    /**
     * 提供给外部的唯一获取实例方法
     *
     * @return 当前类的实例
     */
    public static RetrofitUtils getInstance() {
        synchronized (RetrofitUtils.class) {
            if (sInstance == null) {
                sInstance = new RetrofitUtils();
            }
        }
        return sInstance;
    }

    /**
     * 获取retrofit
     *
     * @return retrofit实例
     */
    public Retrofit getRetrofit() {
        return mRetrofit;
    }

    /**
     * 获取api服务
     *
     * @param tClass 服务接口的class类
     * @param <T>    服务接口的class类
     * @return 返回服务接口类
     */
    public <T> T getServerices(Class<T> tClass) {
        return mRetrofit.create(tClass);
    }
}