├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ ├── activity_auto_cancel_task.xml │ │ │ │ └── activity_main.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── qpg │ │ │ │ └── superhttpdemo │ │ │ │ ├── Test.java │ │ │ │ ├── UserBean.java │ │ │ │ ├── CustomApiFunc.java │ │ │ │ ├── MyObserver.java │ │ │ │ └── AutoCancelTaskActivity.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── qpg │ │ │ └── superhttpdemo │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── qpg │ │ └── superhttpdemo │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── superhttp ├── .gitignore ├── src │ └── main │ │ ├── res │ │ └── values │ │ │ └── strings.xml │ │ ├── java │ │ └── com │ │ │ └── qpg │ │ │ └── superhttp │ │ │ ├── subscriber │ │ │ ├── IProgressDialog.java │ │ │ ├── ProgressCancelListener.java │ │ │ ├── DownCallbackSubscriber.java │ │ │ ├── ApiSubscriber.java │ │ │ └── ApiCallbackSubscriber.java │ │ │ ├── interf │ │ │ └── ILoader.java │ │ │ ├── callback │ │ │ ├── DownloadCallback.java │ │ │ ├── UCallback.java │ │ │ ├── BaseCallback.java │ │ │ ├── SimpleCallBack.java │ │ │ ├── StringCallBack.java │ │ │ ├── LoadingViewCallBack.java │ │ │ └── ProgressDialogCallBack.java │ │ │ ├── cache │ │ │ ├── ICache.java │ │ │ └── DiskCache.java │ │ │ ├── request │ │ │ ├── RetrofitRequest.java │ │ │ ├── GetRequest.java │ │ │ ├── HeadRequest.java │ │ │ ├── PutRequest.java │ │ │ ├── SynRequest.java │ │ │ ├── OptionsRequest.java │ │ │ ├── DeleteRequest.java │ │ │ ├── PatchRequest.java │ │ │ ├── DownloadRequest.java │ │ │ └── PostRequest.java │ │ │ ├── strategy │ │ │ ├── ICacheStrategy.java │ │ │ ├── OnlyCacheStrategy.java │ │ │ ├── OnlyRemoteStrategy.java │ │ │ ├── CacheAndRemoteStrategy.java │ │ │ ├── FirstCacheStrategy.java │ │ │ ├── FirstRemoteStrategy.java │ │ │ └── CacheStrategy.java │ │ │ ├── utils │ │ │ ├── GsonUtil.java │ │ │ ├── MD5Util.java │ │ │ └── CommonUtil.java │ │ │ ├── netexpand │ │ │ ├── convert │ │ │ │ ├── JsonResponseBodyConverter.java │ │ │ │ ├── GsonRequestBodyConverter.java │ │ │ │ ├── GsonResponseBodyConverter.java │ │ │ │ └── GsonConverterFactory.java │ │ │ ├── func │ │ │ │ ├── ApiDataFunc.java │ │ │ │ └── ApiResultFunc.java │ │ │ ├── temp │ │ │ │ ├── IResponseState.java │ │ │ │ ├── Utils.java │ │ │ │ └── DefaultResponseState.java │ │ │ ├── mode │ │ │ │ ├── ResponseCode.java │ │ │ │ └── ApiResult.java │ │ │ ├── common │ │ │ │ └── ResponseHelper.java │ │ │ ├── request │ │ │ │ ├── ApiBaseRequest.java │ │ │ │ ├── ApiGetRequest.java │ │ │ │ └── ApiPostRequest.java │ │ │ └── interceptor │ │ │ │ └── HttpResponseInterceptor.java │ │ │ ├── interceptor │ │ │ ├── NoCacheInterceptor.java │ │ │ ├── HeadersInterceptorNormal.java │ │ │ ├── HeadersInterceptorDynamic.java │ │ │ ├── UploadProgressInterceptor.java │ │ │ ├── OnlineCacheInterceptor.java │ │ │ ├── OfflineCacheInterceptor.java │ │ │ └── GzipRequestInterceptor.java │ │ │ ├── mode │ │ │ ├── CacheMode.java │ │ │ ├── CacheResult.java │ │ │ ├── MediaTypes.java │ │ │ ├── ApiHost.java │ │ │ ├── ApiCode.java │ │ │ ├── DownProgress.java │ │ │ └── HttpHeaders.java │ │ │ ├── cookie │ │ │ ├── store │ │ │ │ ├── CookieStore.java │ │ │ │ ├── MemoryCookieStore.java │ │ │ │ └── SPCookieStore.java │ │ │ └── CookieJarImpl.java │ │ │ ├── transformer │ │ │ ├── ApiFunc.java │ │ │ ├── ApiRetryFunc.java │ │ │ └── DownloadFunction.java │ │ │ ├── config │ │ │ └── SuperConfig.java │ │ │ ├── lifecycle │ │ │ └── BaseLifeCycleObserver.java │ │ │ ├── core │ │ │ ├── ApiTransformer.java │ │ │ ├── ApiManager.java │ │ │ └── ApiCache.java │ │ │ ├── api │ │ │ └── ApiService.java │ │ │ ├── upload │ │ │ └── UploadProgressRequestBody.java │ │ │ └── exception │ │ │ └── ApiException.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── caches │ └── build_file_checksums.ser ├── encodings.xml ├── vcs.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml └── misc.xml ├── .gitignore ├── gradle.properties ├── bintray.gradle ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /superhttp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':superhttp' 2 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SuperHttpDemo 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /superhttp/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SuperHttp 3 | 4 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiaodashaoye/SuperHttp/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/subscriber/IProgressDialog.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.subscriber; 2 | 3 | import android.app.Dialog; 4 | 5 | /** 6 | *

描述:自定义对话框的dialog

7 | */ 8 | public interface IProgressDialog { 9 | Dialog getDialog(); 10 | } 11 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interf/ILoader.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interf; 2 | 3 | /** 4 | * @author qpg 5 | * @date 2017/11/22 0022 6 | * @description: 7 | */ 8 | public interface ILoader { 9 | void showLoader(); 10 | void hideLoader(); 11 | } 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Feb 24 21:52:37 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 7 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/DownloadCallback.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | /** 4 | * @Description: 下载进度回调 5 | */ 6 | public abstract class DownloadCallback extends BaseCallback{ 7 | public abstract void onProgress(long currentLength, long totalLength, float percent); 8 | } 9 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/UCallback.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | /** 4 | * @Description: 上传进度回调 5 | */ 6 | public interface UCallback { 7 | void onProgress(long currentLength, long totalLength, float percent); 8 | void onFail(int errCode, String errMsg); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/subscriber/ProgressCancelListener.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.subscriber; 2 | 3 | /** 4 | *

描述:进度框取消监听

5 | * 作者: zhouyou
6 | * 日期: 2017/5/15 17:09
7 | * 版本: v1.0
8 | */ 9 | public interface ProgressCancelListener { 10 | void onCancelProgress(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/cache/ICache.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.cache; 2 | 3 | /** 4 | * @Description: 缓存接口 5 | */ 6 | public interface ICache { 7 | void put(String key, Object value); 8 | 9 | Object get(String key); 10 | 11 | boolean contains(String key); 12 | 13 | void remove(String key); 14 | 15 | void clear(); 16 | } 17 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/BaseCallback.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | /** 4 | * @Description: 请求接口回调 5 | */ 6 | public abstract class BaseCallback { 7 | public abstract void onStart(); 8 | 9 | public abstract void onSuccess(T data); 10 | 11 | public abstract void onFail(int errCode, String errMsg); 12 | 13 | public abstract void onCompleted(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/qpg/superhttpdemo/Test.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | import androidx.activity.ComponentActivity; 4 | import androidx.lifecycle.Lifecycle; 5 | 6 | public class Test { 7 | public Test(ComponentActivity activity){ 8 | Lifecycle lifecycle= activity.getLifecycle(); 9 | activity.getLifecycle().addObserver(new MyObserver(activity.getLifecycle(),activity)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /superhttp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/RetrofitRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | /** 4 | * @Description: 传入自定义Retrofit接口的请求类型 5 | */ 6 | public class RetrofitRequest extends BaseRequest { 7 | 8 | public RetrofitRequest() { 9 | 10 | } 11 | 12 | public T create(Class cls) { 13 | generateGlobalConfig(); 14 | generateLocalConfig(); 15 | return retrofit.create(cls); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/ICacheStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | import com.qpg.superhttp.core.ApiCache; 4 | import com.qpg.superhttp.mode.CacheResult; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.Observable; 9 | 10 | /** 11 | * @Description: 缓存策略接口 12 | */ 13 | public interface ICacheStrategy { 14 | Observable> execute(ApiCache apiCache, String cacheKey, Observable source, Type type); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_auto_cancel_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/test/java/com/qpg/superhttpdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/subscriber/DownCallbackSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.subscriber; 2 | 3 | import com.qpg.superhttp.callback.BaseCallback; 4 | 5 | /** 6 | * @Description: 包含下载进度回调的订阅者 7 | */ 8 | public class DownCallbackSubscriber extends ApiCallbackSubscriber { 9 | public DownCallbackSubscriber(BaseCallback callBack) { 10 | super(callBack); 11 | } 12 | 13 | @Override 14 | public void onComplete() { 15 | super.onComplete(); 16 | callBack.onSuccess(super.data); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/OnlyCacheStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | import com.qpg.superhttp.core.ApiCache; 4 | import com.qpg.superhttp.mode.CacheResult; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.Observable; 9 | 10 | /** 11 | * @Description: 缓存策略--只取缓存 12 | */ 13 | public class OnlyCacheStrategy extends CacheStrategy { 14 | @Override 15 | public Observable> execute(ApiCache apiCache, String cacheKey, Observable source, Type type) { 16 | return loadCache(apiCache, cacheKey, type); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/OnlyRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | import com.qpg.superhttp.core.ApiCache; 3 | import com.qpg.superhttp.mode.CacheResult; 4 | 5 | import java.lang.reflect.Type; 6 | 7 | import io.reactivex.Observable; 8 | 9 | /** 10 | * @Description: 缓存策略--只取网络 11 | */ 12 | public class OnlyRemoteStrategy extends CacheStrategy { 13 | @Override 14 | public Observable> execute(ApiCache apiCache, String cacheKey, Observable source, Type type) { 15 | return loadRemote(apiCache, cacheKey, source); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/utils/GsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | /** 6 | * @Description: Gson单例操作 7 | */ 8 | public class GsonUtil{ 9 | private static Gson gson; 10 | 11 | public static Gson gson() { 12 | if (gson == null) { 13 | synchronized (Gson.class) { 14 | if (gson == null) { 15 | gson = (new GsonBuilder()).disableHtmlEscaping().create(); 16 | } 17 | } 18 | } 19 | return gson; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/convert/JsonResponseBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.convert; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.ResponseBody; 8 | import retrofit2.Converter; 9 | 10 | /** 11 | * @Description: ResponseBody to T 12 | */ 13 | final class JsonResponseBodyConverter implements Converter { 14 | 15 | JsonResponseBodyConverter() { 16 | } 17 | 18 | @Override 19 | public T convert(@NonNull ResponseBody value) throws IOException { 20 | return (T) value.string(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/SimpleCallBack.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | /** 4 | *

描述:简单的回调,默认可以使用该回调,不用关注其他回调方法

5 | * 使用该回调默认只需要处理onError,onSuccess两个方法既成功失败
6 | */ 7 | public abstract class SimpleCallBack extends BaseCallback { 8 | 9 | @Override 10 | public void onStart() { 11 | // if(!CommonUtil.isConnected(SuperHttp.getContext())){ 12 | // Toast.makeText(SuperHttp.getContext(),"网络连接错误",Toast.LENGTH_LONG).show(); 13 | // onCompleted(); 14 | // } 15 | } 16 | 17 | @Override 18 | public void onCompleted() { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/StringCallBack.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | /** 4 | *

描述:简单的回调,默认可以使用该回调,不用关注其他回调方法

5 | * 使用该回调默认只需要处理onError,onSuccess两个方法既成功失败
6 | */ 7 | public abstract class StringCallBack extends BaseCallback { 8 | 9 | @Override 10 | public void onStart() { 11 | // if(!CommonUtil.isConnected(SuperHttp.getContext())){ 12 | // Toast.makeText(SuperHttp.getContext(),"网络连接错误",Toast.LENGTH_LONG).show(); 13 | // onCompleted(); 14 | // } 15 | } 16 | 17 | @Override 18 | public void onCompleted() { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/func/ApiDataFunc.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.func; 2 | 3 | import com.qpg.superhttp.netexpand.common.ResponseHelper; 4 | import com.qpg.superhttp.netexpand.mode.ApiResult; 5 | 6 | import io.reactivex.functions.Function; 7 | 8 | /** 9 | * @Description: ApiResult转T 10 | */ 11 | public class ApiDataFunc implements Function, T> { 12 | public ApiDataFunc() { 13 | } 14 | 15 | @Override 16 | public T apply(ApiResult response) throws Exception { 17 | if (ResponseHelper.isSuccess(response)) { 18 | return response.getData(); 19 | } 20 | return null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/temp/IResponseState.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.temp; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @Description: 7 | * @date: 2018/1/20 16:27 8 | */ 9 | public interface IResponseState { 10 | //HTTP请求成功状态码 11 | int httpSuccess(); 12 | //AccessToken错误或已过期 13 | int accessTokenExpired(); 14 | //RefreshToken错误或已过期 15 | int refreshTokenExpired(); 16 | //帐号在其它手机已登录 17 | int otherPhoneLogin(); 18 | //时间戳过期 19 | int timestampError(); 20 | //缺少授权信息,没有AccessToken 21 | int noAccessToken(); 22 | //签名错误 23 | int signError(); 24 | //其他错误 25 | List otherError(); 26 | } 27 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/subscriber/ApiSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.subscriber; 2 | 3 | import com.qpg.superhttp.exception.ApiException; 4 | import com.qpg.superhttp.mode.ApiCode; 5 | 6 | import io.reactivex.observers.DisposableObserver; 7 | 8 | /** 9 | * @Description: API统一订阅者 10 | */ 11 | abstract class ApiSubscriber extends DisposableObserver { 12 | 13 | ApiSubscriber() { 14 | 15 | } 16 | 17 | @Override 18 | public void onError(Throwable e) { 19 | if (e instanceof ApiException) { 20 | onError((ApiException) e); 21 | } else { 22 | onError(new ApiException(e, ApiCode.Request.UNKNOWN)); 23 | } 24 | } 25 | 26 | protected abstract void onError(ApiException e); 27 | } 28 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/mode/ResponseCode.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.mode; 2 | 3 | /** 4 | * @Description: Response响应码(根据服务器提供文档进行定义) 5 | */ 6 | public class ResponseCode { 7 | //HTTP请求成功状态码 8 | public static final int HTTP_SUCCESS = 0; 9 | //AccessToken错误或已过期 10 | public static final int ACCESS_TOKEN_EXPIRED = 10001; 11 | //RefreshToken错误或已过期 12 | public static final int REFRESH_TOKEN_EXPIRED = 10002; 13 | //帐号在其它手机已登录 14 | public static final int OTHER_PHONE_LOGIN = 10003; 15 | //时间戳过期 16 | public static final int TIMESTAMP_ERROR = 10004; 17 | //缺少授权信息,没有AccessToken 18 | public static final int NO_ACCESS_TOKEN = 10005; 19 | //签名错误 20 | public static final int SIGN_ERROR = 10006; 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/qpg/superhttpdemo/UserBean.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | /** 4 | * Created by Administrator on 2017/11/9 0009. 5 | */ 6 | 7 | public class UserBean { 8 | private long id; 9 | private String userName; 10 | 11 | public long getId() { 12 | return id; 13 | } 14 | 15 | public void setId(long id) { 16 | this.id = id; 17 | } 18 | 19 | public String getUserName() { 20 | return userName; 21 | } 22 | 23 | public void setUserName(String userName) { 24 | this.userName = userName; 25 | } 26 | 27 | public String getAvatarUrl() { 28 | return avatarUrl; 29 | } 30 | 31 | public void setAvatarUrl(String avatarUrl) { 32 | this.avatarUrl = avatarUrl; 33 | } 34 | 35 | private String avatarUrl; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/temp/Utils.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.temp; 2 | 3 | /** 4 | * @Description: 5 | * @date: 2018/1/20 16:37 6 | */ 7 | public class Utils { 8 | public static T checkNotNull(T t, String message) { 9 | if (t == null) { 10 | throw new NullPointerException(message); 11 | } 12 | return t; 13 | } 14 | 15 | public static T checkIllegalArgument(T t, String message) { 16 | if (t == null) { 17 | throw new IllegalArgumentException(message); 18 | } 19 | return t; 20 | } 21 | 22 | public static void checkIllegalArgument(boolean condition, String message) { 23 | if (condition) { 24 | throw new IllegalArgumentException(message); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /superhttp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/NoCacheInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | 11 | /** 12 | * @Description: 无缓存拦截 13 | */ 14 | public class NoCacheInterceptor implements Interceptor { 15 | 16 | @Override 17 | public Response intercept(@NonNull Chain chain) throws IOException { 18 | Request request = chain.request(); 19 | request = request.newBuilder().header("Cache-Control", "no-cache").build(); 20 | Response originalResponse = chain.proceed(request); 21 | originalResponse = originalResponse.newBuilder().header("Cache-Control", "no-cache").build(); 22 | return originalResponse; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/qpg/superhttpdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.qpg.superhttpdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/mode/CacheMode.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.mode; 2 | 3 | /** 4 | * @Description: 缓存模式 5 | */ 6 | public enum CacheMode { 7 | /** 8 | * 先请求网络,请求网络失败后再加载缓存 9 | */ 10 | FIRST_REMOTE("FirstRemoteStrategy"), 11 | 12 | /** 13 | * 先加载缓存,缓存没有再去请求网络 14 | */ 15 | FIRST_CACHE("FirstCacheStrategy"), 16 | 17 | /** 18 | * 仅加载网络,但数据依然会被缓存 19 | */ 20 | ONLY_REMOTE("OnlyRemoteStrategy"), 21 | 22 | /** 23 | * 只读取缓存 24 | */ 25 | ONLY_CACHE("OnlyCacheStrategy"), 26 | 27 | /** 28 | * 先使用缓存,不管是否存在,仍然请求网络,会回调两次 29 | */ 30 | CACHE_AND_REMOTE("CacheAndRemoteStrategy"); 31 | 32 | private final String className; 33 | 34 | CacheMode(String className) { 35 | this.className = className; 36 | } 37 | 38 | public String getClassName() { 39 | return className; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/cookie/store/CookieStore.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.cookie.store; 2 | 3 | import java.util.List; 4 | 5 | import okhttp3.Cookie; 6 | import okhttp3.HttpUrl; 7 | 8 | public interface CookieStore { 9 | 10 | /** 保存url对应所有cookie */ 11 | void saveCookie(HttpUrl url, List cookie); 12 | 13 | /** 保存url对应所有cookie */ 14 | void saveCookie(HttpUrl url, Cookie cookie); 15 | 16 | /** 加载url所有的cookie */ 17 | List loadCookie(HttpUrl url); 18 | 19 | /** 获取当前所有保存的cookie */ 20 | List getAllCookie(); 21 | 22 | /** 获取当前url对应的所有的cookie */ 23 | List getCookie(HttpUrl url); 24 | 25 | /** 根据url和cookie移除对应的cookie */ 26 | boolean removeCookie(HttpUrl url, Cookie cookie); 27 | 28 | /** 根据url移除所有的cookie */ 29 | boolean removeCookie(HttpUrl url); 30 | 31 | /** 移除所有的cookie */ 32 | boolean removeAllCookie(); 33 | } 34 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/cookie/CookieJarImpl.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.cookie; 2 | 3 | import com.qpg.superhttp.cookie.store.CookieStore; 4 | 5 | import java.util.List; 6 | 7 | import okhttp3.Cookie; 8 | import okhttp3.CookieJar; 9 | import okhttp3.HttpUrl; 10 | 11 | public class CookieJarImpl implements CookieJar { 12 | 13 | private CookieStore cookieStore; 14 | 15 | public CookieJarImpl(CookieStore cookieStore) { 16 | if (cookieStore == null) { 17 | throw new IllegalArgumentException("cookieStore can not be null!"); 18 | } 19 | this.cookieStore = cookieStore; 20 | } 21 | 22 | @Override 23 | public synchronized void saveFromResponse(HttpUrl url, List cookies) { 24 | cookieStore.saveCookie(url, cookies); 25 | } 26 | 27 | @Override 28 | public synchronized List loadForRequest(HttpUrl url) { 29 | return cookieStore.loadCookie(url); 30 | } 31 | 32 | public CookieStore getCookieStore() { 33 | return cookieStore; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/transformer/ApiFunc.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.transformer; 2 | 3 | import com.google.gson.Gson; 4 | import java.io.IOException; 5 | import java.lang.reflect.Type; 6 | import io.reactivex.functions.Function; 7 | import okhttp3.ResponseBody; 8 | 9 | /** 10 | * @Description: ResponseBody转T 11 | */ 12 | public class ApiFunc implements Function { 13 | private Type type; 14 | 15 | public ApiFunc(Type type) { 16 | this.type = type; 17 | } 18 | 19 | @Override 20 | public T apply(ResponseBody responseBody) throws Exception { 21 | Gson gson = new Gson(); 22 | String json; 23 | try { 24 | json = responseBody.string(); 25 | if (type.equals(String.class)) { 26 | return (T) json; 27 | } else { 28 | return gson.fromJson(json, type); 29 | } 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } finally { 33 | responseBody.close(); 34 | } 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/mode/CacheResult.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.mode; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @Description: 设置缓存后的数据返回结果,主要增加是否是缓存数据的区分 7 | */ 8 | public class CacheResult implements Serializable { 9 | private boolean isCache; 10 | private T cacheData; 11 | 12 | public CacheResult(boolean isCache, T cacheData) { 13 | this.isCache = isCache; 14 | this.cacheData = cacheData; 15 | } 16 | 17 | public boolean isCache() { 18 | return isCache; 19 | } 20 | 21 | public CacheResult setCache(boolean cache) { 22 | isCache = cache; 23 | return this; 24 | } 25 | 26 | public T getCacheData() { 27 | return cacheData; 28 | } 29 | 30 | public CacheResult setCacheData(T cacheData) { 31 | this.cacheData = cacheData; 32 | return this; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "CacheResult{" + 38 | "isCache=" + isCache + 39 | ", cacheData=" + cacheData + 40 | '}'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/CacheAndRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | import com.qpg.superhttp.core.ApiCache; 4 | import com.qpg.superhttp.mode.CacheResult; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.functions.Predicate; 10 | 11 | /** 12 | * @Description: 缓存策略--缓存和网络 13 | */ 14 | public class CacheAndRemoteStrategy extends CacheStrategy { 15 | @Override 16 | public Observable> execute(ApiCache apiCache, String cacheKey, Observable source, final Type type) { 17 | Observable> cache = loadCache(apiCache, cacheKey, type); 18 | final Observable> remote = loadRemote(apiCache, cacheKey, source); 19 | return Observable.concat(cache, remote).filter(new Predicate>() { 20 | @Override 21 | public boolean test(CacheResult tCacheResult) throws Exception { 22 | return tCacheResult != null && tCacheResult.getCacheData() != null; 23 | } 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/mode/ApiResult.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.mode; 2 | 3 | /** 4 | * @Description: 封装的通用服务器返回对象,可自行定义 5 | * @date: 2016-12-30 16:43 6 | */ 7 | public class ApiResult { 8 | private int code; 9 | private String msg; 10 | private T data; 11 | 12 | public int getCode() { 13 | return code; 14 | } 15 | 16 | public ApiResult setCode(int code) { 17 | this.code = code; 18 | return this; 19 | } 20 | 21 | public String getMsg() { 22 | return msg; 23 | } 24 | 25 | public ApiResult setMsg(String msg) { 26 | this.msg = msg; 27 | return this; 28 | } 29 | 30 | public T getData() { 31 | return data; 32 | } 33 | 34 | public ApiResult setData(T data) { 35 | this.data = data; 36 | return this; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ApiResult{" + 42 | "code=" + code + 43 | ", msg='" + msg + '\'' + 44 | ", data=" + data + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/HeadersInterceptorNormal.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | import okhttp3.Interceptor; 10 | import okhttp3.Request; 11 | import okhttp3.Response; 12 | 13 | /** 14 | * @Description: 请求头拦截 15 | */ 16 | public class HeadersInterceptorNormal implements Interceptor { 17 | 18 | private Map headers; 19 | 20 | public HeadersInterceptorNormal(Map headers) { 21 | this.headers = headers; 22 | } 23 | 24 | @Override 25 | public Response intercept(@NonNull Chain chain) throws IOException { 26 | Request.Builder builder = chain.request().newBuilder(); 27 | if (headers != null && headers.size() > 0) { 28 | Set keys = headers.keySet(); 29 | for (String headerKey : keys) { 30 | builder.addHeader(headerKey, headers.get(headerKey)).build(); 31 | } 32 | } 33 | return chain.proceed(builder.build()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/qpg/superhttpdemo/CustomApiFunc.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.functions.Function; 9 | import okhttp3.ResponseBody; 10 | 11 | /** 12 | * @Description: 自定义ResponseBody转T, 13 | * 可根据每个项目返回的数据格式自定义,提高了扩展性 14 | */ 15 | public class CustomApiFunc implements Function { 16 | private Type type; 17 | 18 | public CustomApiFunc(Type type) { 19 | this.type = type; 20 | } 21 | 22 | @Override 23 | public T apply(ResponseBody responseBody) throws Exception { 24 | Gson gson = new Gson(); 25 | String json; 26 | try { 27 | json = responseBody.string(); 28 | if (type.equals(String.class)) { 29 | return (T) json; 30 | } else { 31 | return gson.fromJson(json, type); 32 | } 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } finally { 36 | responseBody.close(); 37 | } 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | defaultConfig { 6 | applicationId "com.qpg.superhttpdemo" 7 | minSdkVersion 21 8 | targetSdkVersion 29 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility = '1.8' 21 | targetCompatibility = '1.8' 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(include: ['*.jar'], dir: 'libs') 27 | implementation 'androidx.appcompat:appcompat:1.2.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0-rc1' 29 | testImplementation 'junit:junit:4.13' 30 | androidTestImplementation 'androidx.test:runner:1.3.0-rc03' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-rc03' 32 | api project(':superhttp') 33 | } 34 | -------------------------------------------------------------------------------- /superhttp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 29 5 | 6 | defaultConfig { 7 | minSdkVersion 21 8 | targetSdkVersion 29 9 | versionCode 1 10 | versionName "1.1.3" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | lintOptions { 22 | abortOnError false 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation 'androidx.appcompat:appcompat:1.2.0' 30 | api 'com.squareup.okhttp3:logging-interceptor:4.9.0' 31 | api 'com.squareup.okhttp3:okhttp:4.9.0' 32 | api 'io.reactivex.rxjava2:rxjava:2.2.19' 33 | api 'io.reactivex.rxjava2:rxandroid:2.1.1' 34 | api 'com.squareup.retrofit2:retrofit:2.9.0' 35 | api 'com.squareup.retrofit2:converter-gson:2.9.0' 36 | api 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' 37 | } 38 | apply from: '../bintray.gradle' 39 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/common/ResponseHelper.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.common; 2 | 3 | import com.qpg.superhttp.netexpand.mode.ApiResult; 4 | import com.qpg.superhttp.netexpand.mode.ResponseCode; 5 | 6 | /** 7 | * @Description: 响应处理帮助类 8 | */ 9 | public class ResponseHelper { 10 | 11 | public static boolean isSuccess(ApiResult apiResult) { 12 | if (apiResult == null) { 13 | return false; 14 | } 15 | return apiResult.getCode() == ResponseCode.HTTP_SUCCESS || ignoreSomeIssue(apiResult.getCode()); 16 | } 17 | 18 | private static boolean ignoreSomeIssue(int code) { 19 | switch (code) { 20 | case ResponseCode.TIMESTAMP_ERROR://时间戳过期 21 | case ResponseCode.ACCESS_TOKEN_EXPIRED://AccessToken错误或已过期 22 | case ResponseCode.REFRESH_TOKEN_EXPIRED://RefreshToken错误或已过期 23 | case ResponseCode.OTHER_PHONE_LOGIN://帐号在其它手机已登录 24 | case ResponseCode.NO_ACCESS_TOKEN://缺少授权信息,没有AccessToken 25 | case ResponseCode.SIGN_ERROR://签名错误 26 | return true; 27 | default: 28 | return false; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/temp/DefaultResponseState.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.temp; 2 | 3 | import com.qpg.superhttp.netexpand.mode.ResponseCode; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: 9 | * @date: 2018/1/20 16:31 10 | */ 11 | public class DefaultResponseState implements IResponseState { 12 | @Override 13 | public int httpSuccess() { 14 | return ResponseCode.HTTP_SUCCESS; 15 | } 16 | 17 | @Override 18 | public int accessTokenExpired() { 19 | return ResponseCode.ACCESS_TOKEN_EXPIRED; 20 | } 21 | 22 | @Override 23 | public int refreshTokenExpired() { 24 | return ResponseCode.REFRESH_TOKEN_EXPIRED; 25 | } 26 | 27 | @Override 28 | public int otherPhoneLogin() { 29 | return ResponseCode.OTHER_PHONE_LOGIN; 30 | } 31 | 32 | @Override 33 | public int timestampError() { 34 | return ResponseCode.TIMESTAMP_ERROR; 35 | } 36 | 37 | @Override 38 | public int noAccessToken() { 39 | return ResponseCode.NO_ACCESS_TOKEN; 40 | } 41 | 42 | @Override 43 | public int signError() { 44 | return ResponseCode.SIGN_ERROR; 45 | } 46 | 47 | @Override 48 | public List otherError() { 49 | return null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/HeadersInterceptorDynamic.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | import java.nio.charset.Charset; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | import okhttp3.Interceptor; 11 | import okhttp3.Request; 12 | import okhttp3.Response; 13 | 14 | public class HeadersInterceptorDynamic implements Interceptor { 15 | private final Headers mHeaders; 16 | private static final Charset UTF8 = Charset.forName("UTF-8"); 17 | 18 | public HeadersInterceptorDynamic(Headers headers) { 19 | this.mHeaders = headers; 20 | } 21 | @Override 22 | public Response intercept(@NonNull Chain chain) throws IOException { 23 | Map headers=mHeaders.headers(); 24 | Request.Builder builder = chain.request().newBuilder(); 25 | if (headers != null && headers.size() > 0) { 26 | Set keys = headers.keySet(); 27 | for (String headerKey : keys) { 28 | builder.addHeader(headerKey, headers.get(headerKey)).build(); 29 | } 30 | } 31 | return chain.proceed(builder.build()); 32 | } 33 | public interface Headers{ 34 | Map headers(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | GROUP=com.qpg.net 20 | SITE_URL=https://github.com/qiaodashaoye/SuperHttp 21 | GIT_URL=https://github.com/qiaodashaoye/SuperHttp.git 22 | 23 | PACKAGING=aar 24 | DESCRIBE=This is a lightweight HttpRequest framework 25 | 26 | LICENSE_NAME=The Apache Software License, Version 2.0 27 | LICENSE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 28 | 29 | DEVELOPER_ID=SuperHttp 30 | DEVELOPER_NAME=qpg 31 | DEVELOPER_EMAIL=1451449315@qq.com 32 | 33 | USERORG=q-p-g 34 | PROJECT_REPO=maven 35 | PROJECT_NAME=SuperHttp 36 | PROJECT_PUBLISH=true 37 | android.useAndroidX=true 38 | android.enableJetifier=true -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/UploadProgressInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.qpg.superhttp.upload.UploadProgressRequestBody; 6 | import com.qpg.superhttp.callback.UCallback; 7 | 8 | import java.io.IOException; 9 | 10 | import okhttp3.Interceptor; 11 | import okhttp3.Request; 12 | import okhttp3.Response; 13 | 14 | /** 15 | * @Description: 上传进度拦截 16 | */ 17 | public class UploadProgressInterceptor implements Interceptor { 18 | 19 | private UCallback callback; 20 | 21 | public UploadProgressInterceptor(UCallback callback) { 22 | this.callback = callback; 23 | if (callback == null) { 24 | throw new NullPointerException("this callback must not null."); 25 | } 26 | } 27 | 28 | @Override 29 | public Response intercept(@NonNull Chain chain) throws IOException { 30 | Request originalRequest = chain.request(); 31 | if (originalRequest.body() == null) { 32 | return chain.proceed(originalRequest); 33 | } 34 | Request progressRequest = originalRequest.newBuilder() 35 | .method(originalRequest.method(), 36 | new UploadProgressRequestBody(originalRequest.body(), callback)) 37 | .build(); 38 | return chain.proceed(progressRequest); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/FirstCacheStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | import com.qpg.superhttp.core.ApiCache; 4 | import com.qpg.superhttp.mode.CacheResult; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.functions.Function; 10 | import io.reactivex.functions.Predicate; 11 | 12 | /** 13 | * @Description: 缓存策略--优先缓存 14 | */ 15 | public class FirstCacheStrategy extends CacheStrategy { 16 | @Override 17 | public Observable> execute(ApiCache apiCache, String cacheKey, Observable source, Type type) { 18 | Observable> cache = loadCache(apiCache, cacheKey, type); 19 | cache.onErrorReturn(new Function>() { 20 | @Override 21 | public CacheResult apply(Throwable throwable) throws Exception { 22 | return null; 23 | } 24 | }); 25 | Observable> remote = loadRemote(apiCache, cacheKey, source); 26 | return Observable.concat(cache, remote).filter(new Predicate>() { 27 | @Override 28 | public boolean test(CacheResult tCacheResult) throws Exception { 29 | return tCacheResult != null && tCacheResult.getCacheData() != null; 30 | } 31 | }).firstElement().toObservable(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/FirstRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | import com.qpg.superhttp.core.ApiCache; 4 | import com.qpg.superhttp.mode.CacheResult; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.functions.Function; 10 | import io.reactivex.functions.Predicate; 11 | 12 | /** 13 | * @Description: 缓存策略--优先网络 14 | */ 15 | public class FirstRemoteStrategy extends CacheStrategy { 16 | @Override 17 | public Observable> execute(ApiCache apiCache, String cacheKey, Observable source, Type type) { 18 | Observable> cache = loadCache(apiCache, cacheKey, type); 19 | cache.onErrorReturn(new Function>() { 20 | @Override 21 | public CacheResult apply(Throwable throwable) throws Exception { 22 | return null; 23 | } 24 | }); 25 | Observable> remote = loadRemote(apiCache, cacheKey, source); 26 | return Observable.concat(remote, cache).filter(new Predicate>() { 27 | @Override 28 | public boolean test(CacheResult tCacheResult) throws Exception { 29 | return tCacheResult != null && tCacheResult.getCacheData() != null; 30 | } 31 | }).firstElement().toObservable(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/config/SuperConfig.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.config; 2 | 3 | /** 4 | * @Description: 全局常量配置 5 | */ 6 | public class SuperConfig { 7 | 8 | public static final String CACHE_SP_NAME = "sp_cache";//默认SharedPreferences缓存文件名 9 | public static final String CACHE_DISK_DIR = "disk_cache";//默认磁盘缓存目录 10 | public static final String CACHE_HTTP_DIR = "http_cache";//默认HTTP缓存目录 11 | public static final long CACHE_NEVER_EXPIRE = -1;//永久不过期 12 | 13 | public static final int MAX_AGE_ONLINE = 60;//默认最大在线缓存时间(秒) 14 | public static final int MAX_AGE_OFFLINE = 24 * 60 * 60;//默认最大离线缓存时间(秒) 15 | 16 | public static final String API_HOST = "https://api.github.com/";//默认API主机地址 17 | 18 | public static final String COOKIE_PREFS = "Cookies_Prefs";//默认Cookie缓存目录 19 | 20 | public static final int DEFAULT_TIMEOUT = 60;//默认超时时间(秒) 21 | public static final int DEFAULT_MAX_IDLE_CONNECTIONS = 5;//默认空闲连接数 22 | public static final long DEFAULT_KEEP_ALIVE_DURATION = 8;//默认心跳间隔时长(秒) 23 | public static final long CACHE_MAX_SIZE = 10 * 1024 * 1024;//默认最大缓存大小(字节) 24 | 25 | public static final int DEFAULT_RETRY_COUNT = 3;//默认重试次数 26 | public static final int DEFAULT_RETRY_DELAY_MILLIS = 3000;//默认重试间隔时间(毫秒) 27 | 28 | public static final String DEFAULT_DOWNLOAD_DIR = "download";//默认下载目录 29 | public static final String DEFAULT_DOWNLOAD_FILE_NAME = "download_file.tmp";//默认下载文件名称 30 | } 31 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/subscriber/ApiCallbackSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.subscriber; 2 | 3 | import com.qpg.superhttp.callback.BaseCallback; 4 | import com.qpg.superhttp.exception.ApiException; 5 | 6 | /** 7 | * @Description: 包含回调的订阅者,如果订阅这个,上层在不使用订阅者的情况下可获得回调 8 | */ 9 | public class ApiCallbackSubscriber extends ApiSubscriber { 10 | 11 | BaseCallback callBack; 12 | T data; 13 | 14 | public ApiCallbackSubscriber(BaseCallback callBack) { 15 | if (callBack == null) { 16 | throw new NullPointerException("this callback is null!"); 17 | } 18 | this.callBack = callBack; 19 | } 20 | 21 | @Override 22 | protected void onStart() { 23 | super.onStart(); 24 | if (callBack != null) { 25 | callBack.onStart(); 26 | } 27 | } 28 | 29 | @Override 30 | public void onError(ApiException e) { 31 | if (e == null) { 32 | callBack.onFail(-1, "This ApiException is Null."); 33 | return; 34 | } 35 | callBack.onFail(e.getCode(), e.getMessage()); 36 | } 37 | 38 | @Override 39 | public void onNext(T t) { 40 | this.data = t; 41 | callBack.onSuccess(t); 42 | } 43 | 44 | @Override 45 | public void onComplete() { 46 | if (callBack != null) { 47 | callBack.onCompleted(); 48 | } 49 | } 50 | public T getData() { 51 | return data; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/request/ApiBaseRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.request; 2 | 3 | import com.qpg.superhttp.transformer.ApiRetryFunc; 4 | import com.qpg.superhttp.netexpand.func.ApiDataFunc; 5 | import com.qpg.superhttp.netexpand.mode.ApiResult; 6 | import com.qpg.superhttp.request.BaseHttpRequest; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.ObservableSource; 10 | import io.reactivex.ObservableTransformer; 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * @Description: 返回APIResult的基础请求类 16 | * @date: 17/5/28 15:46. 17 | */ 18 | public abstract class ApiBaseRequest extends BaseHttpRequest { 19 | public ApiBaseRequest(String suffixUrl) { 20 | super(suffixUrl); 21 | } 22 | 23 | protected ObservableTransformer, T> apiTransformer() { 24 | return new ObservableTransformer, T>() { 25 | @Override 26 | public ObservableSource apply(Observable> apiResultObservable) { 27 | return apiResultObservable 28 | .subscribeOn(Schedulers.io()) 29 | .unsubscribeOn(Schedulers.io()) 30 | .observeOn(AndroidSchedulers.mainThread()) 31 | .map(new ApiDataFunc()) 32 | .retryWhen(new ApiRetryFunc(retryCount, retryDelayMillis)); 33 | } 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/convert/GsonRequestBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.convert; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.TypeAdapter; 7 | import com.google.gson.stream.JsonWriter; 8 | 9 | import java.io.IOException; 10 | import java.io.OutputStreamWriter; 11 | import java.io.Writer; 12 | import java.nio.charset.Charset; 13 | 14 | import okhttp3.MediaType; 15 | import okhttp3.RequestBody; 16 | import okio.Buffer; 17 | import retrofit2.Converter; 18 | 19 | /** 20 | * @Description: T to RequestBody 21 | */ 22 | final class GsonRequestBodyConverter implements Converter { 23 | private static final MediaType MEDIA_TYPE = MediaType.parse("init/json; charset=UTF-8"); 24 | private static final Charset UTF_8 = Charset.forName("UTF-8"); 25 | 26 | private final Gson gson; 27 | private final TypeAdapter adapter; 28 | 29 | GsonRequestBodyConverter(Gson gson, TypeAdapter adapter) { 30 | this.gson = gson; 31 | this.adapter = adapter; 32 | } 33 | 34 | @Override 35 | public RequestBody convert(@NonNull T value) throws IOException { 36 | Buffer buffer = new Buffer(); 37 | Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); 38 | JsonWriter jsonWriter = gson.newJsonWriter(writer); 39 | adapter.write(jsonWriter, value); 40 | jsonWriter.close(); 41 | return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.utils; 2 | 3 | import java.security.MessageDigest; 4 | 5 | public class MD5Util { 6 | public static String byteArrayToHexString(byte b[]) { 7 | StringBuffer resultSb = new StringBuffer(); 8 | for (int i = 0; i < b.length; i++) 9 | resultSb.append(byteToHexString(b[i])); 10 | 11 | return resultSb.toString(); 12 | } 13 | 14 | private static String byteToHexString(byte b) { 15 | int n = b; 16 | if (n < 0) { 17 | n += 256; 18 | } 19 | int d1 = n / 16; 20 | int d2 = n % 16; 21 | return hexDigits[d1] + hexDigits[d2]; 22 | } 23 | 24 | public static String MD5Encode(String origin, String charsetname) { 25 | String resultString = null; 26 | try { 27 | resultString = new String(origin); 28 | MessageDigest md = MessageDigest.getInstance("MD5"); 29 | if (charsetname == null || "".equals(charsetname)) { 30 | resultString = byteArrayToHexString(md.digest(resultString 31 | .getBytes())); 32 | } else { 33 | resultString = byteArrayToHexString(md.digest(resultString 34 | .getBytes(charsetname))); 35 | } 36 | } catch (Exception exception) { 37 | } 38 | return resultString; 39 | } 40 | 41 | private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", 42 | "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; 43 | } 44 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/OnlineCacheInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | import android.text.TextUtils; 5 | 6 | import com.qpg.superhttp.config.SuperConfig; 7 | 8 | import java.io.IOException; 9 | 10 | import okhttp3.Interceptor; 11 | import okhttp3.Response; 12 | 13 | /** 14 | * @Description: 在线缓存拦截 15 | */ 16 | public class OnlineCacheInterceptor implements Interceptor { 17 | private String cacheControlValue; 18 | 19 | public OnlineCacheInterceptor() { 20 | this(SuperConfig.MAX_AGE_ONLINE); 21 | } 22 | 23 | public OnlineCacheInterceptor(int cacheControlValue) { 24 | this.cacheControlValue = String.format("max-age=%d", cacheControlValue); 25 | } 26 | 27 | @Override 28 | public Response intercept(@NonNull Chain chain) throws IOException { 29 | Response originalResponse = chain.proceed(chain.request()); 30 | String cacheControl = originalResponse.header("Cache-Control"); 31 | if (TextUtils.isEmpty(cacheControl) || cacheControl.contains("no-store") || cacheControl.contains("no-cache") || cacheControl 32 | .contains("must-revalidate") || cacheControl.contains("max-age") || cacheControl.contains("max-stale")) { 33 | 34 | return originalResponse.newBuilder() 35 | .header("Cache-Control", "public, " + cacheControlValue) 36 | .removeHeader("Pragma") 37 | .build(); 38 | 39 | } else { 40 | return originalResponse; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/mode/MediaTypes.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.mode; 2 | 3 | import okhttp3.MediaType; 4 | 5 | /** 6 | * @Description: MediaType汇总 7 | */ 8 | public class MediaTypes { 9 | public static final MediaType APPLICATION_ATOM_XML_TYPE = MediaType.parse("application/atom+xml;charset=utf-8"); 10 | public static final MediaType APPLICATION_FORM_URLENCODED_TYPE = MediaType.parse("application/x-www-form-urlencoded;charset=utf-8"); 11 | public static final MediaType APPLICATION_JSON_TYPE = MediaType.parse("application/json;charset=utf-8"); 12 | public static final MediaType APPLICATION_OCTET_STREAM_TYPE = MediaType.parse("application/octet-stream"); 13 | public static final MediaType APPLICATION_SVG_XML_TYPE = MediaType.parse("application/svg+xml;charset=utf-8"); 14 | public static final MediaType APPLICATION_XHTML_XML_TYPE = MediaType.parse("application/xhtml+xml;charset=utf-8"); 15 | public static final MediaType APPLICATION_XML_TYPE = MediaType.parse("application/xml;charset=utf-8"); 16 | public static final MediaType MULTIPART_FORM_DATA_TYPE = MediaType.parse("multipart/form-data;charset=utf-8"); 17 | public static final MediaType TEXT_HTML_TYPE = MediaType.parse("text/html;charset=utf-8"); 18 | public static final MediaType TEXT_XML_TYPE = MediaType.parse("text/xml;charset=utf-8"); 19 | public static final MediaType TEXT_PLAIN_TYPE = MediaType.parse("text/plain;charset=utf-8"); 20 | public static final MediaType IMAGE_TYPE = MediaType.parse("image/*"); 21 | public static final MediaType WILDCARD_TYPE = MediaType.parse("*/*"); 22 | } 23 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/mode/ApiHost.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.mode; 2 | 3 | import com.qpg.superhttp.config.SuperConfig; 4 | 5 | /** 6 | * @Description: 主机信息 7 | */ 8 | public class ApiHost { 9 | 10 | private static String host = SuperConfig.API_HOST; 11 | 12 | public static String getHost() { 13 | return host; 14 | } 15 | 16 | public static void setHost(String url) { 17 | setHostHttps(url); 18 | } 19 | 20 | public static void setHostHttp(String url) { 21 | if (url.startsWith("https://") || url.startsWith("http://")) { 22 | host = url; 23 | host = host.replaceAll("https://", "http://"); 24 | } else { 25 | host = "http://" + url; 26 | } 27 | } 28 | 29 | public static void setHostHttps(String url) { 30 | if (url.startsWith("https://") || url.startsWith("http://")) { 31 | host = url; 32 | host = host.replaceAll("http://", "https://"); 33 | } else { 34 | host = "https://" + url; 35 | } 36 | } 37 | 38 | public static String getHttp() { 39 | if (host.startsWith("https://") || host.startsWith("http://")) { 40 | host = host.replaceAll("https://", "http://"); 41 | } else { 42 | host = "http://" + host; 43 | } 44 | return host; 45 | } 46 | 47 | public static String getHttps() { 48 | if (host.startsWith("https://") || host.startsWith("http://")) { 49 | host = host.replaceAll("http://", "https://"); 50 | } else { 51 | host = "https://" + host; 52 | } 53 | return host; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/transformer/ApiRetryFunc.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.transformer; 2 | 3 | import com.qpg.superhttp.exception.ApiException; 4 | 5 | import java.net.ConnectException; 6 | import java.net.SocketTimeoutException; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import io.reactivex.Observable; 10 | import io.reactivex.ObservableSource; 11 | import io.reactivex.functions.Function; 12 | 13 | /** 14 | * @Description: 重试机制 15 | */ 16 | public class ApiRetryFunc implements Function, Observable> { 17 | 18 | private final int maxRetries; 19 | private final int retryDelayMillis; 20 | private int retryCount; 21 | 22 | public ApiRetryFunc(int maxRetries, int retryDelayMillis) { 23 | this.maxRetries = maxRetries; 24 | this.retryDelayMillis = retryDelayMillis; 25 | } 26 | 27 | @Override 28 | public Observable apply(Observable observable) throws Exception { 29 | return observable 30 | .flatMap(new Function>() { 31 | @Override 32 | public ObservableSource apply(Throwable throwable) throws Exception { 33 | if (++retryCount <= maxRetries && (throwable instanceof SocketTimeoutException 34 | || throwable instanceof ConnectException)) { 35 | return Observable.timer(retryDelayMillis, TimeUnit.MILLISECONDS); 36 | } 37 | return Observable.error(ApiException.handleException(throwable)); 38 | } 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/OfflineCacheInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | 6 | import com.qpg.superhttp.utils.CommonUtil; 7 | import com.qpg.superhttp.config.SuperConfig; 8 | 9 | import java.io.IOException; 10 | 11 | import okhttp3.CacheControl; 12 | import okhttp3.Interceptor; 13 | import okhttp3.Request; 14 | import okhttp3.Response; 15 | 16 | /** 17 | * @Description: 离线缓存拦截 18 | */ 19 | public class OfflineCacheInterceptor implements Interceptor { 20 | private Context context; 21 | private String cacheControlValue; 22 | 23 | public OfflineCacheInterceptor(Context context) { 24 | this(context, SuperConfig.MAX_AGE_OFFLINE); 25 | } 26 | 27 | public OfflineCacheInterceptor(Context context, int cacheControlValue) { 28 | this.context = context; 29 | this.cacheControlValue = String.format("max-stale=%d", cacheControlValue); 30 | } 31 | 32 | @Override 33 | public Response intercept(@NonNull Chain chain) throws IOException { 34 | Request request = chain.request(); 35 | if (!CommonUtil.isConnected(context)) { 36 | request = request.newBuilder() 37 | .cacheControl(CacheControl.FORCE_CACHE) 38 | .build(); 39 | Response response = chain.proceed(request); 40 | return response.newBuilder() 41 | .header("Cache-Control", "public, only-if-cached, " + cacheControlValue) 42 | .removeHeader("Pragma") 43 | .build(); 44 | } 45 | return chain.proceed(request); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/mode/ApiCode.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.mode; 2 | 3 | /** 4 | * @Description: 网络通用状态码定义 5 | */ 6 | public class ApiCode { 7 | 8 | /** 9 | * 对应HTTP的状态码 10 | */ 11 | public static class Http { 12 | public static final int OK = 200;//请求成功。一般用于GET与POST请求 13 | public static final int Bad_Request = 400;//1、客户端请求的语法错误,服务器无法理解。2、请求参数有误。 14 | public static final int UNAUTHORIZED = 401;//请求要求用户的身份认证 15 | public static final int FORBIDDEN = 403;//服务器理解请求客户端的请求,但是拒绝执行此请求 16 | public static final int NOT_FOUND = 404; 17 | public static final int REQUEST_TIMEOUT = 408;//服务器等待客户端发送的请求时间过长,超时 18 | public static final int INTERNAL_SERVER_ERROR = 500;//服务器内部错误,无法完成请求 19 | public static final int BAD_GATEWAY = 502;//作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 20 | public static final int SERVICE_UNAVAILABLE = 503;//由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 21 | public static final int GATEWAY_TIMEOUT = 504;//充当网关或代理的服务器,未及时从远端服务器获取请求 22 | } 23 | 24 | /** 25 | * Request请求码 26 | */ 27 | public static class Request { 28 | //未知错误 29 | public static final int UNKNOWN = 1000; 30 | //解析错误 31 | public static final int PARSE_ERROR = 1001; 32 | //网络错误 33 | public static final int NETWORK_ERROR = 1002; 34 | //协议出错 35 | public static final int HTTP_ERROR = 1003; 36 | //证书出错 37 | public static final int SSL_ERROR = 1005; 38 | //连接超时 39 | public static final int TIMEOUT_ERROR = 1006; 40 | //调用错误 41 | public static final int INVOKE_ERROR = 1007; 42 | //类转换错误 43 | public static final int CONVERT_ERROR = 1008; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/interceptor/GzipRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.interceptor; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.Interceptor; 8 | import okhttp3.MediaType; 9 | import okhttp3.Request; 10 | import okhttp3.RequestBody; 11 | import okhttp3.Response; 12 | import okio.BufferedSink; 13 | import okio.GzipSink; 14 | import okio.Okio; 15 | 16 | /** 17 | * @Description: 包含Gzip压缩的请求拦截 18 | */ 19 | public class GzipRequestInterceptor implements Interceptor { 20 | @Override 21 | public Response intercept(@NonNull Chain chain) throws IOException { 22 | Request originalRequest = chain.request(); 23 | if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { 24 | return chain.proceed(originalRequest); 25 | } 26 | Request compressedRequest = originalRequest.newBuilder().header("Accept-Encoding", "gzip").method(originalRequest.method(), gzip 27 | (originalRequest.body())).build(); 28 | return chain.proceed(compressedRequest); 29 | } 30 | 31 | private RequestBody gzip(final RequestBody body) { 32 | return new RequestBody() { 33 | @Override 34 | public MediaType contentType() { 35 | return body.contentType(); 36 | } 37 | 38 | @Override 39 | public long contentLength() { 40 | return -1; 41 | } 42 | 43 | @Override 44 | public void writeTo(@NonNull BufferedSink sink) throws IOException { 45 | BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); 46 | body.writeTo(gzipSink); 47 | gzipSink.close(); 48 | } 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/lifecycle/BaseLifeCycleObserver.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.lifecycle; 2 | 3 | import android.app.Activity; 4 | import android.util.Log; 5 | 6 | import androidx.fragment.app.Fragment; 7 | import androidx.lifecycle.Lifecycle; 8 | import androidx.lifecycle.LifecycleObserver; 9 | import androidx.lifecycle.OnLifecycleEvent; 10 | 11 | import com.qpg.superhttp.SuperHttp; 12 | 13 | public class BaseLifeCycleObserver implements LifecycleObserver { 14 | 15 | private Activity mActivity; 16 | private Fragment mFragment; 17 | private Lifecycle mLifecycle; 18 | private static final String TAG = "1-------->"; 19 | public BaseLifeCycleObserver(Lifecycle lifecycle, Activity activity){ 20 | mActivity=activity; 21 | mLifecycle=lifecycle; 22 | } 23 | public BaseLifeCycleObserver(Lifecycle lifecycle, Fragment fragment){ 24 | mFragment=fragment; 25 | mLifecycle=lifecycle; 26 | } 27 | 28 | // 使用注解 @OnLifecycleEvent 来表明该方法需要监听指定的生命周期事件 29 | @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 30 | public void connectListener() { 31 | Log.d(TAG, "connectListener: -------- onResume" ); 32 | } 33 | 34 | @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 35 | public void disconnectListener() { 36 | Log.d(TAG, "disconnectListener: ------- onPause"); 37 | } 38 | 39 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 40 | public void destroyListener() { 41 | mLifecycle.removeObserver(this); 42 | if(mActivity!=null){ 43 | SuperHttp.cancelSome(mActivity.getClass().getName()); 44 | } 45 | if(mFragment!=null){ 46 | SuperHttp.cancelSome(mFragment.getClass().getName()); 47 | } 48 | Log.d(TAG, "destroyListener: ------- onDestroy"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/qpg/superhttpdemo/MyObserver.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttpdemo; 2 | 3 | import android.app.Activity; 4 | import android.util.Log; 5 | import androidx.fragment.app.Fragment; 6 | import androidx.lifecycle.Lifecycle; 7 | import androidx.lifecycle.LifecycleObserver; 8 | import androidx.lifecycle.OnLifecycleEvent; 9 | import com.qpg.superhttp.SuperHttp; 10 | 11 | public class MyObserver implements LifecycleObserver { 12 | 13 | private Activity mActivity; 14 | private Fragment mFragment; 15 | private Lifecycle mLifecycle; 16 | private static final String TAG = "MyObserver"; 17 | public MyObserver(Lifecycle lifecycle,Activity activity){ 18 | mActivity=activity; 19 | mLifecycle=lifecycle; 20 | mActivity.getClass().getName(); 21 | } 22 | public MyObserver(Lifecycle lifecycle,Fragment fragment){ 23 | mFragment=fragment; 24 | mLifecycle=lifecycle; 25 | mActivity.getClass().getName(); 26 | } 27 | 28 | // 使用注解 @OnLifecycleEvent 来表明该方法需要监听指定的生命周期事件 29 | @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 30 | public void connectListener() { 31 | // ... 32 | Log.d(TAG, "connectListener: -------- onResume" ); 33 | } 34 | 35 | @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 36 | public void disconnectListener() { 37 | // ... 38 | Log.d(TAG, "disconnectListener: ------- onPause"); 39 | } 40 | 41 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 42 | public void destroyListener() { 43 | mLifecycle.removeObserver(this); 44 | if(mActivity!=null){ 45 | SuperHttp.cancelSome(mActivity.getClass().getName()); 46 | } 47 | if(mFragment!=null){ 48 | SuperHttp.cancelSome(mFragment.getClass().getName()); 49 | } 50 | // ... 51 | Log.d(TAG, "destroyListener: ------- onPause"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/convert/GsonResponseBodyConverter.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.convert; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.TypeAdapter; 7 | import com.google.gson.stream.JsonReader; 8 | import com.qpg.superhttp.netexpand.common.ResponseHelper; 9 | import com.qpg.superhttp.netexpand.mode.ApiResult; 10 | 11 | import java.io.IOException; 12 | import java.net.UnknownServiceException; 13 | 14 | import okhttp3.ResponseBody; 15 | import retrofit2.Converter; 16 | 17 | /** 18 | * @Description: ResponseBody to T 19 | */ 20 | final class GsonResponseBodyConverter implements Converter { 21 | private final Gson gson; 22 | private final TypeAdapter adapter; 23 | 24 | GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) { 25 | this.gson = gson; 26 | this.adapter = adapter; 27 | } 28 | 29 | @Override 30 | public T convert(@NonNull ResponseBody value) throws IOException { 31 | if (adapter != null && gson != null) { 32 | JsonReader jsonReader = gson.newJsonReader(value.charStream()); 33 | try { 34 | T data = adapter.read(jsonReader); 35 | if (data == null) throw new UnknownServiceException("server back data is null"); 36 | if (data instanceof ApiResult) { 37 | ApiResult apiResult = (ApiResult) data; 38 | if (!ResponseHelper.isSuccess(apiResult)) { 39 | throw new UnknownServiceException(apiResult.getMsg() == null ? "unknow error" : apiResult.getMsg()); 40 | } 41 | } 42 | return data; 43 | } finally { 44 | value.close(); 45 | } 46 | } else { 47 | return null; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/core/ApiTransformer.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.core; 2 | 3 | import com.qpg.superhttp.config.HttpGlobalConfig; 4 | import com.qpg.superhttp.transformer.ApiRetryFunc; 5 | 6 | import io.reactivex.Observable; 7 | import io.reactivex.ObservableSource; 8 | import io.reactivex.ObservableTransformer; 9 | import io.reactivex.android.schedulers.AndroidSchedulers; 10 | import io.reactivex.schedulers.Schedulers; 11 | 12 | /** 13 | * @Description: 转换器 14 | */ 15 | public class ApiTransformer { 16 | 17 | public static ObservableTransformer norTransformer() { 18 | return new ObservableTransformer() { 19 | @Override 20 | public ObservableSource apply(Observable apiResultObservable) { 21 | return apiResultObservable 22 | .subscribeOn(Schedulers.io()) 23 | .unsubscribeOn(Schedulers.io()) 24 | .observeOn(AndroidSchedulers.mainThread()) 25 | .retryWhen(new ApiRetryFunc(HttpGlobalConfig.getInstance().getRetryCount(), 26 | HttpGlobalConfig.getInstance().getRetryDelayMillis())); 27 | } 28 | }; 29 | } 30 | 31 | public static ObservableTransformer norTransformer(final int retryCount, final int retryDelayMillis) { 32 | return new ObservableTransformer() { 33 | @Override 34 | public ObservableSource apply(Observable apiResultObservable) { 35 | return apiResultObservable 36 | .subscribeOn(Schedulers.io()) 37 | .unsubscribeOn(Schedulers.io()) 38 | .observeOn(AndroidSchedulers.mainThread()) 39 | .retryWhen(new ApiRetryFunc(retryCount, retryDelayMillis)); 40 | } 41 | }; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/convert/GsonConverterFactory.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.convert; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import java.lang.annotation.Annotation; 8 | import java.lang.reflect.Type; 9 | 10 | import okhttp3.RequestBody; 11 | import okhttp3.ResponseBody; 12 | import retrofit2.Converter; 13 | import retrofit2.Retrofit; 14 | 15 | /** 16 | * @Description: GSON转换工厂 17 | */ 18 | public class GsonConverterFactory extends Converter.Factory { 19 | private final Gson gson; 20 | 21 | private GsonConverterFactory(Gson gson) { 22 | if (gson == null) throw new NullPointerException("gson == null"); 23 | this.gson = gson; 24 | } 25 | 26 | public static GsonConverterFactory create() { 27 | return create(new Gson()); 28 | } 29 | 30 | public static GsonConverterFactory create(Gson gson) { 31 | return new GsonConverterFactory(gson); 32 | } 33 | 34 | @Override 35 | public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { 36 | if (type != null && type.equals(String.class)) { 37 | return new JsonResponseBodyConverter<>(); 38 | } 39 | TypeAdapter adapter = null; 40 | if (type != null) { 41 | adapter = gson.getAdapter(TypeToken.get(type)); 42 | } 43 | return new GsonResponseBodyConverter<>(gson, adapter); 44 | } 45 | 46 | @Override 47 | public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, 48 | Retrofit retrofit) { 49 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); 50 | return new GsonRequestBodyConverter<>(gson, adapter); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/strategy/CacheStrategy.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.strategy; 2 | 3 | 4 | import com.qpg.superhttp.utils.GsonUtil; 5 | import com.qpg.superhttp.core.ApiCache; 6 | import com.qpg.superhttp.mode.CacheResult; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | import io.reactivex.Observable; 11 | import io.reactivex.functions.Consumer; 12 | import io.reactivex.functions.Function; 13 | import io.reactivex.functions.Predicate; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * @Description: 缓存策略 18 | */ 19 | abstract class CacheStrategy implements ICacheStrategy { 20 | Observable> loadCache(final ApiCache apiCache, final String key, final Type type) { 21 | return apiCache.get(key).filter(new Predicate() { 22 | @Override 23 | public boolean test(String s) throws Exception { 24 | return s != null; 25 | } 26 | }).map(new Function>() { 27 | @Override 28 | public CacheResult apply(String s) throws Exception { 29 | T t = GsonUtil.gson().fromJson(s, type); 30 | 31 | return new CacheResult<>(true, t); 32 | } 33 | }); 34 | } 35 | 36 | Observable> loadRemote(final ApiCache apiCache, final String key, Observable source) { 37 | return source.map(new Function>() { 38 | @Override 39 | public CacheResult apply(T t) throws Exception { 40 | 41 | apiCache.put(key, t).subscribeOn(Schedulers.io()).subscribe(new Consumer() { 42 | @Override 43 | public void accept(Boolean status) throws Exception { 44 | 45 | } 46 | }); 47 | return new CacheResult<>(false, t); 48 | } 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/utils/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | 9 | public class CommonUtil { 10 | 11 | /** 12 | * @return 当前程序的版本名称 13 | */ 14 | public static String getVersionName(Context context) { 15 | String version; 16 | try { 17 | PackageManager pm = context.getPackageManager(); 18 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 19 | version = packageInfo.versionName; 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | 23 | version = ""; 24 | } 25 | return version; 26 | } 27 | /** 28 | * 方法: getVersionCode 29 | * 描述: 获取客户端版本号 30 | * 31 | * @return int 版本号 32 | */ 33 | public static int getVersionCode(Context context) { 34 | int versionCode; 35 | try { 36 | PackageManager pm = context.getPackageManager(); 37 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 38 | versionCode = packageInfo.versionCode; 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | 42 | versionCode = 999; 43 | } 44 | return versionCode; 45 | } 46 | 47 | /** 48 | * 判断网络连接是否有效(此时可传输数据)。 49 | * 50 | * @return boolean 不管wifi,还是mobile net,只有当前在连接状态(可有效传输数据)才返回true,反之false。 51 | */ 52 | public static boolean isConnected(Context context) { 53 | NetworkInfo net = getConnectivityManager(context).getActiveNetworkInfo(); 54 | return net != null && net.isConnected(); 55 | } 56 | 57 | /** 58 | * 获取ConnectivityManager 59 | */ 60 | public static ConnectivityManager getConnectivityManager(Context context) { 61 | return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/callback/LoadingViewCallBack.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.callback; 2 | 3 | import android.widget.Toast; 4 | import com.qpg.superhttp.SuperHttp; 5 | import com.qpg.superhttp.interf.ILoader; 6 | import com.qpg.superhttp.subscriber.IProgressDialog; 7 | import com.qpg.superhttp.subscriber.ProgressCancelListener; 8 | import com.qpg.superhttp.utils.CommonUtil; 9 | import io.reactivex.disposables.Disposable; 10 | 11 | /** 12 | *

描述:可以自定义带有加载进度框的回调

13 | * 1.可以自定义带有加载进度框的回调,是否需要显示,是否可以取消
14 | * 2.取消对话框会自动取消掉网络请求
15 | */ 16 | public abstract class LoadingViewCallBack extends BaseCallback implements ProgressCancelListener { 17 | private ILoader iLoader; 18 | private String onFailMsg; 19 | 20 | public LoadingViewCallBack(ILoader iLoader) { 21 | this.iLoader = iLoader; 22 | 23 | } 24 | public LoadingViewCallBack(ILoader iLoader, String onFailMsg) { 25 | this.iLoader = iLoader; 26 | this.onFailMsg = onFailMsg; 27 | } 28 | 29 | @Override 30 | public void onStart() { 31 | if(!CommonUtil.isConnected(SuperHttp.getContext())){ 32 | Toast.makeText(SuperHttp.getContext(),"网络连接错误",Toast.LENGTH_SHORT).show(); 33 | onFail(0,""); 34 | }else { 35 | iLoader.showLoader(); 36 | } 37 | 38 | } 39 | 40 | @Override 41 | public void onFail(int errCode, String errMsg) { 42 | if(!CommonUtil.isConnected(SuperHttp.getContext())){ 43 | return; 44 | } 45 | if(onFailMsg!=null){ 46 | Toast.makeText(SuperHttp.getContext(),onFailMsg,Toast.LENGTH_SHORT).show(); 47 | } 48 | 49 | iLoader.hideLoader(); 50 | } 51 | 52 | @Override 53 | public void onCompleted() { 54 | iLoader.hideLoader(); 55 | } 56 | 57 | 58 | @Override 59 | public void onCancelProgress() { 60 | if (disposed != null && !disposed.isDisposed()) { 61 | disposed.dispose(); 62 | } 63 | } 64 | 65 | private Disposable disposed; 66 | 67 | public void subscription(Disposable disposed) { 68 | this.disposed = disposed; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/GetRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | import com.qpg.superhttp.SuperHttp; 4 | import com.qpg.superhttp.callback.BaseCallback; 5 | import com.qpg.superhttp.core.ApiManager; 6 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 7 | import com.qpg.superhttp.mode.CacheResult; 8 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.observers.DisposableObserver; 14 | 15 | /** 16 | * @Description: Get请求 17 | */ 18 | public class GetRequest extends BaseHttpRequest { 19 | public GetRequest(String suffixUrl) { 20 | super(suffixUrl); 21 | } 22 | 23 | @Override 24 | protected Observable execute(Type type) { 25 | return apiService.get(suffixUrl, params).compose(this.norTransformer(type)); 26 | } 27 | 28 | @Override 29 | protected Observable> cacheExecute(Type type) { 30 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 31 | } 32 | 33 | @Override 34 | protected void execute(BaseCallback callback) { 35 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 36 | if (super.tag != null) { 37 | ApiManager.get().add(super.tag, disposableObserver); 38 | 39 | } 40 | 41 | if (super.mActivity != null) { 42 | if (!ApiManager.get().isContainTag(mActivity.getClass().getName())) { 43 | mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(mActivity.getLifecycle(), mActivity)); 44 | } 45 | ApiManager.get().add(mActivity.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 46 | } 47 | 48 | if (super.mFragment != null) { 49 | if (!ApiManager.get().isContainTag(mFragment.getClass().getName())) { 50 | mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(mFragment.getLifecycle(), mFragment)); 51 | } 52 | ApiManager.get().add(mFragment.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 53 | } 54 | 55 | if (isLocalCache) { 56 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 57 | } else { 58 | this.execute(getType(callback)).subscribe(disposableObserver); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/HeadRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | 4 | import com.qpg.superhttp.SuperHttp; 5 | import com.qpg.superhttp.callback.BaseCallback; 6 | import com.qpg.superhttp.core.ApiManager; 7 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 8 | import com.qpg.superhttp.mode.CacheResult; 9 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 10 | 11 | import java.lang.reflect.Type; 12 | 13 | import io.reactivex.Observable; 14 | import io.reactivex.observers.DisposableObserver; 15 | 16 | /** 17 | * @Description: Head请求 18 | */ 19 | public class HeadRequest extends BaseHttpRequest { 20 | public HeadRequest(String suffixUrl) { 21 | super(suffixUrl); 22 | } 23 | 24 | @Override 25 | protected Observable execute(Type type) { 26 | return apiService.head(suffixUrl, params).compose(this.norTransformer(type)); 27 | } 28 | 29 | @Override 30 | protected Observable> cacheExecute(Type type) { 31 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 32 | } 33 | 34 | @Override 35 | protected void execute(BaseCallback callback) { 36 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 37 | if (super.tag != null) { 38 | ApiManager.get().add(super.tag, disposableObserver); 39 | } 40 | 41 | if (super.mActivity != null) { 42 | if(!ApiManager.get().isContainTag(super.mActivity.getClass().getName())){ 43 | super.mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mActivity.getLifecycle(),super.mActivity)); 44 | } 45 | ApiManager.get().add(super.mActivity.getClass().getName()+"_"+disposableObserver.hashCode(), disposableObserver); 46 | } 47 | 48 | if (super.mFragment != null) { 49 | if(!ApiManager.get().isContainTag(super.mFragment.getClass().getName())){ 50 | super.mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mFragment.getLifecycle(),mFragment)); 51 | } 52 | ApiManager.get().add(super.mFragment.getClass().getName()+"_"+disposableObserver.hashCode(), disposableObserver); 53 | } 54 | 55 | if (isLocalCache) { 56 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 57 | } else { 58 | this.execute(getType(callback)).subscribe(disposableObserver); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/PutRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | import com.qpg.superhttp.SuperHttp; 4 | import com.qpg.superhttp.callback.BaseCallback; 5 | import com.qpg.superhttp.core.ApiManager; 6 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 7 | import com.qpg.superhttp.mode.CacheResult; 8 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.observers.DisposableObserver; 14 | 15 | /** 16 | * @Description: Put请求 17 | */ 18 | public class PutRequest extends BaseHttpRequest { 19 | public PutRequest(String suffixUrl) { 20 | super(suffixUrl); 21 | } 22 | 23 | @Override 24 | protected Observable execute(Type type) { 25 | return apiService.put(suffixUrl, params).compose(this.norTransformer(type)); 26 | } 27 | 28 | @Override 29 | protected Observable> cacheExecute(Type type) { 30 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 31 | } 32 | 33 | @Override 34 | protected void execute(BaseCallback callback) { 35 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 36 | if (super.tag != null) { 37 | ApiManager.get().add(super.tag, disposableObserver); 38 | } 39 | 40 | if (super.mActivity != null) { 41 | if (!ApiManager.get().isContainTag(super.mActivity.getClass().getName())) { 42 | super.mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mActivity.getLifecycle(), super.mActivity)); 43 | } 44 | ApiManager.get().add(super.mActivity.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 45 | } 46 | 47 | if (super.mFragment != null) { 48 | if (!ApiManager.get().isContainTag(super.mFragment.getClass().getName())) { 49 | super.mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mFragment.getLifecycle(), mFragment)); 50 | } 51 | ApiManager.get().add(super.mFragment.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 52 | } 53 | 54 | if (isLocalCache) { 55 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 56 | } else { 57 | this.execute(getType(callback)).subscribe(disposableObserver); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/SynRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | import com.qpg.superhttp.SuperHttp; 4 | import com.qpg.superhttp.callback.BaseCallback; 5 | import com.qpg.superhttp.core.ApiManager; 6 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 7 | import com.qpg.superhttp.mode.CacheResult; 8 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.observers.DisposableObserver; 14 | 15 | /** 16 | * @Description: 同步请求 17 | */ 18 | public class SynRequest extends BaseHttpRequest { 19 | public SynRequest(String suffixUrl) { 20 | super(suffixUrl); 21 | } 22 | 23 | @Override 24 | protected Observable execute(Type type) { 25 | return apiService.get(suffixUrl, params).compose(this.norTransformer(type)); 26 | } 27 | 28 | @Override 29 | protected Observable> cacheExecute(Type type) { 30 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 31 | } 32 | 33 | @Override 34 | protected void execute(BaseCallback callback) { 35 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 36 | if (super.tag != null) { 37 | ApiManager.get().add(super.tag, disposableObserver); 38 | } 39 | 40 | if (super.mActivity != null) { 41 | if (!ApiManager.get().isContainTag(super.mActivity.getClass().getName())) { 42 | super.mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mActivity.getLifecycle(), super.mActivity)); 43 | } 44 | ApiManager.get().add(super.mActivity.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 45 | } 46 | 47 | if (super.mFragment != null) { 48 | if (!ApiManager.get().isContainTag(super.mFragment.getClass().getName())) { 49 | super.mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mFragment.getLifecycle(), mFragment)); 50 | } 51 | ApiManager.get().add(super.mFragment.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 52 | } 53 | 54 | if (isLocalCache) { 55 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 56 | } else { 57 | this.execute(getType(callback)).subscribe(disposableObserver); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/func/ApiResultFunc.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.func; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.qpg.superhttp.utils.GsonUtil; 6 | import com.qpg.superhttp.netexpand.mode.ApiResult; 7 | import com.qpg.superhttp.netexpand.mode.ResponseCode; 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | import java.io.IOException; 12 | import java.lang.reflect.Type; 13 | 14 | import io.reactivex.functions.Function; 15 | import okhttp3.ResponseBody; 16 | 17 | /** 18 | * @Description: ResponseBody转ApiResult 19 | */ 20 | public class ApiResultFunc implements Function> { 21 | protected Type type; 22 | 23 | public ApiResultFunc(Type type) { 24 | this.type = type; 25 | } 26 | 27 | @Override 28 | public ApiResult apply(ResponseBody responseBody) throws Exception { 29 | ApiResult apiResult = new ApiResult<>(); 30 | apiResult.setCode(-1); 31 | try { 32 | String json = responseBody.string(); 33 | ApiResult result = parseApiResult(json, apiResult); 34 | if (result != null) { 35 | apiResult = result; 36 | if (apiResult.getData() != null) { 37 | T data = GsonUtil.gson().fromJson(apiResult.getData().toString(), type); 38 | apiResult.setData(data); 39 | apiResult.setCode(ResponseCode.HTTP_SUCCESS); 40 | } else { 41 | apiResult.setMsg("ApiResult's data is null"); 42 | } 43 | } else { 44 | apiResult.setMsg("json is null"); 45 | } 46 | } catch (JSONException | IOException e) { 47 | e.printStackTrace(); 48 | apiResult.setMsg(e.getMessage()); 49 | } finally { 50 | responseBody.close(); 51 | } 52 | return apiResult; 53 | } 54 | 55 | private ApiResult parseApiResult(String json, ApiResult apiResult) throws JSONException { 56 | if (TextUtils.isEmpty(json)) return null; 57 | JSONObject jsonObject = new JSONObject(json); 58 | if (jsonObject.has("code")) { 59 | apiResult.setCode(jsonObject.getInt("code")); 60 | } 61 | if (jsonObject.has("data")) { 62 | apiResult.setData(jsonObject.getString("data")); 63 | } 64 | if (jsonObject.has("msg")) { 65 | apiResult.setMsg(jsonObject.getString("msg")); 66 | } 67 | return apiResult; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/request/OptionsRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.request; 2 | 3 | import com.qpg.superhttp.SuperHttp; 4 | import com.qpg.superhttp.callback.BaseCallback; 5 | import com.qpg.superhttp.core.ApiManager; 6 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 7 | import com.qpg.superhttp.mode.CacheResult; 8 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.observers.DisposableObserver; 14 | 15 | /** 16 | * @Description: Options请求 17 | */ 18 | public class OptionsRequest extends BaseHttpRequest { 19 | public OptionsRequest(String suffixUrl) { 20 | super(suffixUrl); 21 | } 22 | 23 | @Override 24 | protected Observable execute(Type type) { 25 | return apiService.options(suffixUrl, params).compose(this.norTransformer(type)); 26 | } 27 | 28 | @Override 29 | protected Observable> cacheExecute(Type type) { 30 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 31 | } 32 | 33 | @Override 34 | protected void execute(BaseCallback callback) { 35 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 36 | if (super.tag != null) { 37 | ApiManager.get().add(super.tag, disposableObserver); 38 | } 39 | 40 | if (super.mActivity != null) { 41 | if (!ApiManager.get().isContainTag(super.mActivity.getClass().getName())) { 42 | super.mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mActivity.getLifecycle(), super.mActivity)); 43 | } 44 | ApiManager.get().add(super.mActivity.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 45 | } 46 | 47 | if (super.mFragment != null) { 48 | if (!ApiManager.get().isContainTag(super.mFragment.getClass().getName())) { 49 | super.mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(super.mFragment.getLifecycle(), mFragment)); 50 | } 51 | ApiManager.get().add(super.mFragment.getClass().getName() + "_" + disposableObserver.hashCode(), disposableObserver); 52 | } 53 | 54 | if (isLocalCache) { 55 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 56 | } else { 57 | this.execute(getType(callback)).subscribe(disposableObserver); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/netexpand/request/ApiGetRequest.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.netexpand.request; 2 | 3 | import com.qpg.superhttp.SuperHttp; 4 | import com.qpg.superhttp.callback.BaseCallback; 5 | import com.qpg.superhttp.core.ApiManager; 6 | import com.qpg.superhttp.lifecycle.BaseLifeCycleObserver; 7 | import com.qpg.superhttp.mode.CacheResult; 8 | import com.qpg.superhttp.netexpand.func.ApiResultFunc; 9 | import com.qpg.superhttp.subscriber.ApiCallbackSubscriber; 10 | 11 | import java.lang.reflect.Type; 12 | 13 | import io.reactivex.Observable; 14 | import io.reactivex.observers.DisposableObserver; 15 | 16 | /** 17 | * @Description: 返回APIResult的GET请求类 18 | * @date: 17/5/13 14:31. 19 | */ 20 | public class ApiGetRequest extends ApiBaseRequest { 21 | public ApiGetRequest(String suffixUrl) { 22 | super(suffixUrl); 23 | } 24 | 25 | @Override 26 | protected Observable execute(Type type) { 27 | return apiService.get(suffixUrl, params).map(new ApiResultFunc(type)).compose(this.apiTransformer()); 28 | } 29 | 30 | @Override 31 | protected Observable> cacheExecute(Type type) { 32 | return this.execute(type).compose(SuperHttp.getApiCache().transformer(cacheMode, type)); 33 | } 34 | 35 | @Override 36 | protected void execute(BaseCallback callback) { 37 | DisposableObserver disposableObserver = new ApiCallbackSubscriber(callback); 38 | if (super.tag != null) { 39 | ApiManager.get().add(super.tag, disposableObserver); 40 | } 41 | if (super.mActivity != null) { 42 | String tag=String.valueOf(mActivity.getClass().getName()+"_"+System.nanoTime()); 43 | if(!ApiManager.get().isContainTag(tag)){ 44 | mActivity.getLifecycle().addObserver(new BaseLifeCycleObserver(mActivity.getLifecycle(),mActivity)); 45 | } 46 | ApiManager.get().add(tag, disposableObserver); 47 | } 48 | if (super.mFragment != null) { 49 | String tag=String.valueOf(mFragment.getClass().getName()+"_"+System.nanoTime()); 50 | if(!ApiManager.get().isContainTag(tag)){ 51 | mFragment.getLifecycle().addObserver(new BaseLifeCycleObserver(mFragment.getLifecycle(),mFragment)); 52 | } 53 | ApiManager.get().add(tag, disposableObserver); 54 | } 55 | if (isLocalCache) { 56 | this.cacheExecute(getSubType(callback)).subscribe(disposableObserver); 57 | } else { 58 | this.execute(getType(callback)).subscribe(disposableObserver); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /bintray.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.dcendents.android-maven' 2 | apply plugin: 'com.jfrog.bintray' 3 | // ./gradlew build bintrayUpload -PbintrayUser=q-p-g -PbintrayKey=f66f6ed4c5aec926f236eae5b0325731024997c2 -PdryRun=false 4 | //gradlew bintrayUpload -PbintrayUser=q-p-p -PbintrayKey=f66f6ed4c5aec926f236eae5b0325731024997c2 -PdryRun=false 5 | version = android.defaultConfig.versionName 6 | group = GROUP 7 | 8 | install { 9 | repositories.mavenInstaller { 10 | pom { 11 | project { 12 | packaging PACKAGING 13 | name DESCRIBE 14 | url SITE_URL 15 | licenses { 16 | license { 17 | name LICENSE_NAME 18 | url LICENSE_URL 19 | } 20 | } 21 | developers { 22 | developer { 23 | id DEVELOPER_ID 24 | name DEVELOPER_NAME 25 | email DEVELOPER_EMAIL 26 | } 27 | } 28 | scm { 29 | connection GIT_URL 30 | developerConnection GIT_URL 31 | url SITE_URL 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | task sourcesJar(type: Jar) { 39 | from android.sourceSets.main.java.srcDirs 40 | classifier = 'sources' 41 | } 42 | 43 | task javadoc(type: Javadoc) { 44 | options.encoding = "UTF-8" 45 | source = android.sourceSets.main.java.srcDirs 46 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 47 | } 48 | 49 | task javadocJar(type: Jar, dependsOn: javadoc) { 50 | classifier = 'javadoc' 51 | from javadoc.destinationDir 52 | } 53 | 54 | tasks.withType(JavaCompile) { 55 | options.encoding = "UTF-8" 56 | } 57 | 58 | tasks.withType(Javadoc) { 59 | options.addStringOption('Xdoclint:none', '-quiet') 60 | options.addStringOption('encoding', 'UTF-8') 61 | options.addStringOption('charSet', 'UTF-8') 62 | } 63 | 64 | artifacts { 65 | archives javadocJar 66 | archives sourcesJar 67 | } 68 | 69 | Properties properties = new Properties() 70 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 71 | bintray { 72 | user = properties.getProperty("bintray.user") 73 | key = properties.getProperty("bintray.apikey") 74 | configurations = ['archives'] 75 | pkg { 76 | repo = PROJECT_REPO 77 | name = PROJECT_NAME 78 | websiteUrl = SITE_URL 79 | vcsUrl = GIT_URL 80 | licenses = ["Apache-2.0"] 81 | publish = PROJECT_PUBLISH 82 | } 83 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /superhttp/src/main/java/com/qpg/superhttp/core/ApiManager.java: -------------------------------------------------------------------------------- 1 | package com.qpg.superhttp.core; 2 | 3 | import java.util.Set; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import io.reactivex.disposables.Disposable; 6 | 7 | /** 8 | * @Description: 请求管理,方便中途取消请求 9 | */ 10 | public class ApiManager { 11 | private static ApiManager sInstance; 12 | 13 | private ConcurrentHashMap arrayMaps; 14 | 15 | public static ApiManager get() { 16 | if (sInstance == null) { 17 | synchronized (ApiManager.class) { 18 | if (sInstance == null) { 19 | sInstance = new ApiManager(); 20 | } 21 | } 22 | } 23 | return sInstance; 24 | } 25 | 26 | private ApiManager() { 27 | arrayMaps = new ConcurrentHashMap<>(); 28 | } 29 | public ConcurrentHashMap getTagMap(){ 30 | return arrayMaps; 31 | } 32 | public void add(Object tag, Disposable disposable) { 33 | arrayMaps.put(tag, disposable); 34 | } 35 | 36 | public void remove(Object tag) { 37 | if (!arrayMaps.isEmpty()) { 38 | arrayMaps.remove(tag); 39 | } 40 | } 41 | 42 | public void removeAll() { 43 | if (!arrayMaps.isEmpty()) { 44 | arrayMaps.clear(); 45 | } 46 | } 47 | 48 | public void cancel(Object tag) { 49 | if (arrayMaps.isEmpty()) { 50 | return; 51 | } 52 | if (tag == null) { 53 | return; 54 | } 55 | if (arrayMaps.get(tag) == null) { 56 | return; 57 | } 58 | if (!arrayMaps.get(tag).isDisposed()) { 59 | arrayMaps.get(tag).dispose(); 60 | 61 | arrayMaps.remove(tag); 62 | } 63 | } 64 | 65 | public void cancelSome(String subTag) { 66 | if (arrayMaps.isEmpty()) { 67 | return; 68 | } 69 | Set keys = arrayMaps.keySet(); 70 | for (Object apiKey : keys) { 71 | if(apiKey instanceof String && ((String) apiKey).contains(subTag)){ 72 | cancel(apiKey); 73 | } 74 | } 75 | } 76 | public boolean isContainTag(String subTag) { 77 | 78 | Set keys = arrayMaps.keySet(); 79 | for (Object apiKey : keys) { 80 | // System.out.println("122-------->"+apiKey); 81 | if(apiKey instanceof String && ((String) apiKey).contains(subTag)){ 82 | // System.out.println("22-------->"+apiKey); 83 | return true; 84 | } 85 | } 86 | return false; 87 | } 88 | public void cancelAll() { 89 | if (arrayMaps.isEmpty()) { 90 | return; 91 | } 92 | Set keys = arrayMaps.keySet(); 93 | for (Object apiKey : keys) { 94 | cancel(apiKey); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 |