public interface FileResponseResult {

    void onSuccess();

    void onFailure(Throwable throwable, String content);
} public abstract class HttpCallback<T> {

    public static final String TAG = "HttpCallback";

    protected Type genericityType;

    public HttpCallback() {
        Type genericSuperclass = getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            this.genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
        } else {
            this.genericityType = Object.class;
        }
    }

    public abstract void onResolve(T t);

    public abstract void onFailed(String err_code, String message);

    public Type getGenericityType() {
        return genericityType;
    }

} public class DownloadInterceptor implements Interceptor {

    private TransformProgressListener progressListener;
    private DownloadInfo downloadInfo;

    public DownloadInterceptor() {
    }

    public DownloadInterceptor(DownloadInfo downloadInfo, TransformProgressListener progressListener) {
        this.progressListener = progressListener;
        this.downloadInfo = downloadInfo;
    }

    public void setDownloadInfo(DownloadInfo downloadInfo) {
        this.downloadInfo = downloadInfo;
    }

    public void setProgressListener(TransformProgressListener progressListener) {
        this.progressListener = progressListener;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request().newBuilder().addHeader("RANGE", "bytes=" + downloadInfo.getReadLength() + "-").build();
        Response originalResponse = chain.proceed(request);
        DownloadResponseBody body = new DownloadResponseBody(originalResponse.body(), progressListener);
        Response response = originalResponse.newBuilder().body(body).build();
        return response;
    }

    public static DownloadInterceptor create(DownloadInfo downloadInfo, TransformProgressListener progressListener) {
        return new DownloadInterceptor(downloadInfo, progressListener);
    }

} public class HeaderAddInterceptor implements Interceptor {

    private Map<String, String> headers = new HashMap<>();

    public HeaderAddInterceptor(Map<String, String> headers) {
        this.headers = headers;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request.Builder builder = chain.request().newBuilder();
        for (String key : headers.keySet()) {
            builder.addHeader(key, headers.get(key));
        }
        Request request = builder.build();
        return chain.proceed(request);
    }
} public class OffLineIntercept implements Interceptor {

    private Context mContext;

    public OffLineIntercept(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!NetworkUtils.isNetworkConnected(mContext)) {
            CacheControl cacheControl = new CacheControl.Builder()
                    .maxStale(1, TimeUnit.DAYS)
                    .build();
            request = request.newBuilder()
                    .cacheControl(cacheControl)
                    .build();
        }
        return chain.proceed(request);
    }

    public static OffLineIntercept create(Context context){
        return new OffLineIntercept(context);
    }
} public class UploadFileInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
                .newBuilder()
                .addHeader("Content-Type", "multipart/form-data")
                .build();
        return chain.proceed(request);
    }

    public static UploadFileInterceptor create() {
        return new UploadFileInterceptor();
    }
} public interface CommonRequest {

    @GET("{path}")
    Observable<ResponseBody> doGet(@Path(value = "path", encoded = true) String url, @QueryMap Map<String, Object> map);

    @GET("{path}")
    Observable<ResponseBody> doGet(@Path(value = "path", encoded = true) String url, @Body RequestBody map);

    @GET("{path}")
    Observable<ResponseBody> doGet(@Path(value = "path", encoded = true) String url);

    /**
     * 参数含有@Field和@FieldMap的请求必须加@FormUrlEncoded
     * Post请求最好用@Field,@Query也行，只是参数会暴露在Url中
     *
     * @param url
     * @param map
     * @return
     */
    @FormUrlEncoded
    @POST("{path}")
    Observable<ResponseBody> doPost(@Path(value = "path", encoded = true) String url, @FieldMap Map<String, Object> map);

    @POST("{path}")
    Observable<ResponseBody> doPost(@Path(value = "path", encoded = true) String url, @Body RequestBody body);

    @FormUrlEncoded
    @PUT("{path}")
    Observable<ResponseBody> doPut(@Path(value = "path", encoded = true) String url, @FieldMap Map<String, Object> map);

    @PUT("{path}")
    Observable<ResponseBody> doPut(@Path(value = "path", encoded = true) String url, @Body RequestBody body);

    @DELETE("{path}")
    Observable<ResponseBody> doDelete(@Path(value = "path", encoded = true) String url);

    @DELETE("{path}")
    Observable<ResponseBody> doDelete(@Path(value = "path", encoded = true) String url, @QueryMap Map<String, Object> maps);

    @HTTP(method = "DELETE", path = "{path}", hasBody = true)
    Observable<ResponseBody> doDelete(@Path(value = "path", encoded = true) String url, @Body RequestBody body);

    /**
     * 完整路径
     *
     * @param url
     * @return
     */
    @GET
    Observable<ResponseBody> doGetFullPath(@Url String url);

    /**
     * 完整路径
     *
     * @param url
     * @param map
     * @return
     */
    @GET
    Observable<ResponseBody> doGetFullPath(@Url String url, @QueryMap Map<String, Object> map);

    /**
     * 参数含有@Field和@FieldMap的请求必须加@FormUrlEncoded
     * Post请求最好用@Field,@Query也行，只是参数会暴露在Url中
     *
     * @param url 完整路径
     * @param map
     * @return
     */
    @FormUrlEncoded
    @POST
    Observable<ResponseBody> doPostFullPath(@Url String url, @FieldMap Map<String, Object> map);

    @Multipart
    @POST("{path}")
    Observable<ResponseBody> uploadFile(@Path(value = "path", encoded = true) String url,
                                        @Part("description") RequestBody description, @Part MultipartBody.Part file);

    @Multipart
    @POST
    Observable<ResponseBody> uploadFileFullPath(@Url String url,
                                                @Part("description") RequestBody description, @Part MultipartBody.Part file);

    @Multipart
    @POST("{path}")
    Observable<ResponseBody> uploadFiles(
            @Path(value = "path", encoded = true) String url,
            @PartMap Map<String, RequestBody> maps);

    @Multipart
    @POST
    Observable<ResponseBody> uploadFilesFullPath(
            @Url String url,
            @PartMap() Map<String, RequestBody> maps);

    //支持大文件
    @Streaming
    @GET
    Observable<ResponseBody> download(@Url String fileUrl);
} public class CommonResultSubscriber<T extends ResponseBody> extends Subscriber<T> {

    public static final String TAG = "CommonResultSubscriber";

    private Context mContext;
    private boolean showLoadingDailog = false;
    private String loadingMsg;

    private LoadingCallback loadingCallback;
    private HttpCallback httpCallback;

    /**
     * 不带加载框回调
     *
     * @param mContext
     * @param callback
     */
    public CommonResultSubscriber(Context mContext, HttpCallback callback) {
        this.mContext = mContext;
        this.httpCallback = callback;
    }

    /**
     * 带加载框回调
     *
     * @param mContext
     * @param callback
     * @param loadingMsg
     */
    public CommonResultSubscriber(Context mContext, HttpCallback callback, String loadingMsg) {
        this.mContext = mContext;
        this.httpCallback = callback;
        this.loadingMsg = loadingMsg;

        if (!TextUtils.isEmpty(loadingMsg)) {
            try {
                loadingCallback = (LoadingCallback) mContext;
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (loadingCallback != null) {
                showLoadingDailog = true;
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (showLoadingDailog && loadingCallback != null) {
            loadingCallback.onStartLoading(loadingMsg);
        }
    }

    @Override
    public void onCompleted() {
        if (showLoadingDailog) {
            loadingCallback.onFinishLoading();
        }
    }

    @Override
    public void onError(Throwable e) {
        if (showLoadingDailog && loadingCallback != null) {
            loadingCallback.onFinishLoading();
        }
        e.printStackTrace();
        if (httpCallback != null) {
            httpCallback.onFailed("failure", e.getMessage());
        }
    }

    @Override
    public void onNext(T t) {
        if (t.contentLength() == 0) {
            return;
        }
        if (httpCallback != null) {
            boolean returnJson = false;
            Type genericityType = httpCallback.getGenericityType();
            if (genericityType instanceof Class) {
                switch (((Class) genericityType).getSimpleName()) {
                    case "Object":
                    case "String":
                        returnJson = true;
                        break;
                    default:
                        break;
                }
            }

            if (returnJson) {
                try {
                    httpCallback.onResolve(t.string());
                } catch (IOException e) {
                    httpCallback.onFailed("failure", e.getMessage());
                    e.printStackTrace();
                }
            } else {
                try {
                    this.httpCallback.onResolve((new Gson()).fromJson(t.string(), genericityType));
                } catch (Exception e) {
                    httpCallback.onFailed("failure", e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }
} public class UploadFileRequestBody extends RequestBody {

    private RequestBody mRequestBody;
    private TransformProgressListener mProgressListener;

    private BufferedSink bufferedSink;


    public UploadFileRequestBody(File file , TransformProgressListener progressListener) {
        this.mRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file) ;
        this.mProgressListener = progressListener ;
    }

    public UploadFileRequestBody(RequestBody requestBody, TransformProgressListener progressListener) {
        this.mRequestBody = requestBody;
        this.mProgressListener = progressListener;
    }

    //返回了requestBody的类型，想什么form-data/MP3/MP4/png等等等格式
    @Override
    public MediaType contentType() {
        return mRequestBody.contentType();
    }

    //返回了本RequestBody的长度，也就是上传的totalLength
    @Override
    public long contentLength() throws IOException {
        return mRequestBody.contentLength();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (bufferedSink == null) {
            //包装
            bufferedSink = Okio.buffer(sink(sink));
        }
        //写入
        mRequestBody.writeTo(bufferedSink);
        //必须调用flush，否则最后一部分数据可能不会被写入
        bufferedSink.flush();
    }

    private Sink sink(Sink sink) {
        return new ForwardingSink(sink) {
            //当前写入字节数
            long bytesWritten = 0L;
            //总字节长度，避免多次调用contentLength()方法
            long contentLength = 0L;

            @Override
            public void write(Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                if (contentLength == 0) {
                    //获得contentLength的值，后续不再调用
                    contentLength = contentLength();
                }
                //增加当前写入的字节数
                bytesWritten += byteCount;
                //回调上传接口
                mProgressListener.onProgress(bytesWritten, contentLength, bytesWritten == contentLength);
            }
        };
    }
} public class UploadSubscriber<T extends ResponseBody> extends Subscriber<T> {

    private Context mContext;
    private boolean showLoadingDailog = false;
    private String loadingMsg;

    private LoadingCallback loadingCallback;
    private FileResponseResult callback;

    /**
     * 不带加载框回调
     *
     * @param mContext
     * @param callback
     */
    public UploadSubscriber(Context mContext, FileResponseResult callback) {
        this.mContext = mContext;
        this.callback = callback;
    }

    /**
     * 带加载框回调
     *
     * @param mContext
     * @param callback
     * @param loadingMsg
     */
    public UploadSubscriber(Context mContext, FileResponseResult callback, String loadingMsg) {
        this.mContext = mContext;
        this.callback = callback;
        this.loadingMsg = loadingMsg;

        if (!TextUtils.isEmpty(loadingMsg)) {
            try {
                loadingCallback = (LoadingCallback) mContext;
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (loadingCallback != null) {
                showLoadingDailog = true;
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (showLoadingDailog) {
            loadingCallback.onStartLoading(loadingMsg);
        }
    }

    @Override
    public void onCompleted() {
        if (showLoadingDailog) {
            loadingCallback.onFinishLoading();
        }
        callback.onSuccess();
    }

    @Override
    public void onError(Throwable e) {
        if (showLoadingDailog) {
            loadingCallback.onFinishLoading();
        }
        callback.onFailure(e, "服务器错误");
    }

    @Override
    public void onNext(T t) {
        if (t.contentLength() == 0) {
            return;
        }
//        Gson gson = new Gson();
//        TypeAdapter<?> adapter = gson.getAdapter(callback.getGenericityType());
//        JsonReader jsonReader = gson.newJsonReader(t.charStream());
//        try {
//            callback.onNext(adapter.read(jsonReader));
//        } catch (IOException e) {
//            callback.onFailure(e, e.getMessage());
//            e.printStackTrace();
//        }
    }
}
import android.content.Context;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.jady.retrofitclient.callback.FileResponseResult;
import com.jady.retrofitclient.callback.HttpCallback;
import com.jady.retrofitclient.download.DownloadInterceptor;
import com.jady.retrofitclient.interceptor.HeaderAddInterceptor;
import com.jady.retrofitclient.interceptor.OffLineIntercept;
import com.jady.retrofitclient.interceptor.UploadFileInterceptor;
import com.jady.retrofitclient.request.CommonRequest;
import com.jady.retrofitclient.subscriber.CommonResultSubscriber;
import com.jady.retrofitclient.upload.UploadFileRequestBody;
import com.jady.retrofitclient.upload.UploadSubscriber;
import java.io.File;
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.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
                .subscribe(new CommonResultSubscriber(mContext, callback));
    }

    public void syncPost(Context context, String url, Map<String, Object> parameters, HttpCallback callback) {
        this.mContext = context;
        FormBody.Builder builder = new FormBody.Builder();
        if (parameters != null && parameters.size() > 0) {
            for (Map.Entry<String, Object> map : parameters.entrySet()) {
                builder.add(map.getKey(), String.valueOf(map.getValue()));
            }
        }
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        Call call = getOkHttpClient().newCall(request);
        try {
            Response response = call.execute();
            if (response.isSuccessful()) {
                callback.onResolve(response.body().string());
            } else {
                callback.onFailed("failure", response.message());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void postFullPath(Context context, String fullUrl, Map<String, Object> parameters, HttpCallback callback) {
        this.mContext = context;
        commonRequest
                .doPostFullPath(fullUrl, parameters)
                .compose(schedulerTransformer)
                .subscribe(new CommonResultSubscriber(mContext, callback));
    }

    /**
     * 回调形式
     *
     * @param context
     * @param url
     * @param parameters
     * @param callback
     */
    public void get(Context context, String url, Map<String, Object> parameters, HttpCallback callback) {
        mContext = context;

        if (parameters == null || parameters.size() == 0) {
            commonRequest
                    .doGet(url)
                    .compose(schedulerTransformer)
                    .subscribe(new CommonResultSubscriber(mContext, callback));
        } else {
            commonRequest
                    .doGet(url, parameters)
                    .compose(schedulerTransformer)
                    .subscribe(new CommonResultSubscriber(mContext, callback));
        }
    }

    /**
     * RxJava形式
     *
     * @param context
     * @param url
     * @param parameters
     * @return
     */
    public Observable get(Context context, String url, Map<String, Object> parameters) {
        mContext = context;

        if (parameters == null || parameters.size() == 0) {
            return commonRequest
                    .doGet(url)
                    .compose(schedulerTransformer);
        } else {
            return commonRequest
                    .doGet(url, parameters)
                    .compose(schedulerTransformer);
        }
    }

    public void syncGet(Context context, String url, Map<String, Object> parameters, HttpCallback callback) {
        this.mContext = context;
        StringBuilder sb = new StringBuilder();
        sb.append(url);
        if (parameters != null && parameters.size() > 0) {
            sb.append("?");
            for (Map.Entry<String, Object> map : parameters.entrySet()) {
                sb.append(map.getKey()).append("=").append(map.getValue()).append("&");
            }
            sb.deleteCharAt(sb.lastIndexOf("&"));
        }
        Request request = new Request.Builder().url(sb.toString()).build();
        Call call = getOkHttpClient().newCall(request);
        try {
            Response response = call.execute();
            if (response.isSuccessful()) {
                callback.onResolve(response.body().string());
            } else {
                callback.onFailed("failure", response.message());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void getFullPath(Context context, String fullUrl, Map<String, Object> parameters, HttpCallback callback) {
        mContext = context;

        if (parameters == null || parameters.size() == 0) {
            commonRequest
                    .doGetFullPath(fullUrl)
                    .compose(schedulerTransformer)
                    .subscribe(new CommonResultSubscriber(mContext, callback));
        } else {
            commonRequest
                    .doGetFullPath(fullUrl, parameters)
                    .compose(schedulerTransformer)
                    .subscribe(new CommonResultSubscriber(mContext, callback));
        }
    }

    public void uploadFile(String url, String filePath, String fileDes, boolean isFullUrl, final FileResponseResult callback) {