├── 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_main.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── wls │ │ │ │ └── wn │ │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── wls │ │ │ └── wn │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── wls │ │ └── wn │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── wnlibrary ├── .gitignore ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── wls │ │ │ │ └── wnlibrary │ │ │ │ └── utils │ │ │ │ ├── net │ │ │ │ ├── subsciber │ │ │ │ │ ├── ProgressCancelListener.java │ │ │ │ │ ├── IProgressDialog.java │ │ │ │ │ ├── CallBackSubsciber.java │ │ │ │ │ ├── BaseSubscriber.java │ │ │ │ │ └── ProgressSubscriber.java │ │ │ │ ├── callback │ │ │ │ │ ├── IType.java │ │ │ │ │ ├── SimpleCallBack.java │ │ │ │ │ ├── DownloadProgressCallBack.java │ │ │ │ │ ├── CallClazzProxy.java │ │ │ │ │ ├── CallBack.java │ │ │ │ │ ├── CallBackProxy.java │ │ │ │ │ └── ProgressDialogCallBack.java │ │ │ │ ├── body │ │ │ │ │ ├── ProgressResponseCallBack.java │ │ │ │ │ ├── RequestBodyUtils.java │ │ │ │ │ ├── UploadProgressRequestBody.java │ │ │ │ │ └── UIProgressResponseCallBack.java │ │ │ │ ├── func │ │ │ │ │ ├── CacheResultFunc.java │ │ │ │ │ ├── HandleFuc.java │ │ │ │ │ ├── HttpResponseFunc.java │ │ │ │ │ └── RetryExceptionFunc.java │ │ │ │ ├── exception │ │ │ │ │ └── ServerException.java │ │ │ │ ├── transformer │ │ │ │ │ └── HandleErrTransformer.java │ │ │ │ ├── cache │ │ │ │ │ ├── stategy │ │ │ │ │ │ ├── OnlyCacheStrategy.java │ │ │ │ │ │ ├── IStrategy.java │ │ │ │ │ │ ├── FirstCacheStategy.java │ │ │ │ │ │ ├── CacheAndRemoteStrategy.java │ │ │ │ │ │ ├── OnlyRemoteStrategy.java │ │ │ │ │ │ ├── NoStrategy.java │ │ │ │ │ │ ├── FirstRemoteStrategy.java │ │ │ │ │ │ └── CacheAndRemoteDistinctStrategy.java │ │ │ │ │ ├── core │ │ │ │ │ │ ├── MemoryCache.java │ │ │ │ │ │ ├── CacheCore.java │ │ │ │ │ │ ├── BaseCache.java │ │ │ │ │ │ └── LruDiskCache.java │ │ │ │ │ ├── converter │ │ │ │ │ │ ├── IDiskConverter.java │ │ │ │ │ │ ├── SerializableDiskConverter.java │ │ │ │ │ │ └── GsonDiskConverter.java │ │ │ │ │ └── model │ │ │ │ │ │ ├── CacheResult.java │ │ │ │ │ │ └── CacheMode.java │ │ │ │ ├── interceptor │ │ │ │ │ ├── NoCacheInterceptor.java │ │ │ │ │ ├── HeadersInterceptor.java │ │ │ │ │ ├── CacheInterceptor.java │ │ │ │ │ ├── BaseExpiredInterceptor.java │ │ │ │ │ ├── GzipRequestInterceptor.java │ │ │ │ │ └── CacheInterceptorOffline.java │ │ │ │ ├── model │ │ │ │ │ └── ApiResult.java │ │ │ │ ├── utils │ │ │ │ │ ├── HttpUtil.java │ │ │ │ │ └── RxUtil.java │ │ │ │ ├── cookie │ │ │ │ │ ├── CookieManger.java │ │ │ │ │ └── SerializableOkHttpCookies.java │ │ │ │ ├── JsonJieXi.java │ │ │ │ ├── request │ │ │ │ │ ├── DownloadRequest.java │ │ │ │ │ ├── DeleteRequest.java │ │ │ │ │ ├── PostRequest.java │ │ │ │ │ ├── GetRequest.java │ │ │ │ │ ├── PutRequest.java │ │ │ │ │ └── CustomRequest.java │ │ │ │ └── api │ │ │ │ │ └── ApiService.java │ │ │ │ ├── pic │ │ │ │ ├── TuPianJiaZai.java │ │ │ │ ├── PaletteTarget.java │ │ │ │ └── GlidePalette.java │ │ │ │ └── base │ │ │ │ └── BaseFragment.java │ │ ├── res │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ └── layout │ │ │ │ └── shanglajiazai_weibuju.xml │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── wls │ │ │ └── wnlibrary │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── wls │ │ └── wnlibrary │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── .gradle ├── 4.4 │ ├── fileChanges │ │ └── last-build.bin │ ├── fileHashes │ │ ├── fileHashes.bin │ │ ├── fileHashes.lock │ │ └── resourceHashesCache.bin │ ├── javaCompile │ │ ├── taskJars.bin │ │ ├── jarAnalysis.bin │ │ ├── javaCompile.lock │ │ ├── taskHistory.bin │ │ └── classAnalysis.bin │ ├── fileContent │ │ └── fileContent.lock │ └── taskHistory │ │ ├── taskHistory.bin │ │ └── taskHistory.lock └── buildOutputCleanup │ ├── cache.properties │ ├── outputFiles.bin │ └── buildOutputCleanup.lock ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── caches │ └── build_file_checksums.ser ├── encodings.xml ├── vcs.xml ├── libraries │ ├── Gradle__com_google_code_findbugs_jsr305_2_0_1_jar.xml │ ├── Gradle__com_android_support_constraint_constraint_layout_solver_1_1_2_jar.xml │ ├── Gradle__net_sf_kxml_kxml2_2_3_0_jar.xml │ ├── Gradle__com_android_support_constraint_constraint_layout_1_1_2_aar.xml │ ├── Gradle__android_arch_core_common_1_1_0_jar.xml │ ├── Gradle__io_reactivex_rxjava2_rxjava_2_1_1_jar.xml │ ├── Gradle__android_arch_lifecycle_common_1_1_0_jar.xml │ ├── Gradle__com_jakewharton_disklrucache_2_0_2_jar.xml │ ├── Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_2_30_jar.xml │ ├── Gradle__com_github_bumptech_glide_annotations_4_8_0_jar.xml │ ├── Gradle__com_github_bumptech_glide_disklrucache_4_8_0_jar.xml │ ├── Gradle__org_reactivestreams_reactive_streams_1_0_0_jar.xml │ ├── Gradle__com_squareup_retrofit2_adapter_rxjava2_2_3_0_jar.xml │ ├── Gradle__org_jetbrains_kotlin_kotlin_stdlib_jre7_1_2_30_jar.xml │ ├── Gradle__com_android_support_support_annotations_27_1_1_jar.xml │ ├── Gradle__com_squareup_okhttp3_logging_interceptor_3_1_2_jar.xml │ ├── Gradle__android_arch_core_runtime_1_1_0_aar.xml │ ├── Gradle__junit_junit_4_12_jar.xml │ ├── Gradle__com_android_support_design_27_1_1_aar.xml │ ├── Gradle__android_arch_lifecycle_runtime_1_1_0_aar.xml │ ├── Gradle__com_android_support_percent_27_1_1_aar.xml │ ├── Gradle__com_android_support_test_runner_1_0_2_aar.xml │ ├── Gradle__com_github_bumptech_glide_glide_4_8_0_aar.xml │ ├── Gradle__com_android_support_test_monitor_1_0_2_aar.xml │ ├── Gradle__io_reactivex_rxjava2_rxandroid_2_0_1_aar.xml │ ├── Gradle__android_arch_lifecycle_viewmodel_1_1_0_aar.xml │ ├── Gradle__com_android_support_palette_v7_27_1_1_aar.xml │ ├── Gradle__com_android_support_support_v4_27_1_1_aar.xml │ ├── Gradle__com_android_support_transition_27_1_1_aar.xml │ ├── Gradle__com_android_support_appcompat_v7_27_1_1_aar.xml │ ├── Gradle__android_arch_lifecycle_livedata_core_1_1_0_aar.xml │ ├── Gradle__com_android_support_support_compat_27_1_1_aar.xml │ ├── Gradle__com_google_code_gson_gson_2_7_jar.xml │ ├── Gradle__com_android_support_recyclerview_v7_27_1_1_aar.xml │ ├── Gradle__com_android_support_support_core_ui_27_1_1_aar.xml │ ├── Gradle__com_squareup_okio_okio_1_13_0_jar.xml │ ├── Gradle__javax_inject_javax_inject_1_jar.xml │ ├── Gradle__com_android_support_support_fragment_27_1_1_aar.xml │ ├── Gradle__com_android_support_support_core_utils_27_1_1_aar.xml │ ├── Gradle__com_squareup_javawriter_2_1_1_jar.xml │ ├── Gradle__com_android_support_test_espresso_espresso_core_3_0_2_aar.xml │ ├── Gradle__org_jetbrains_annotations_13_0_jar.xml │ ├── Gradle__com_android_support_support_media_compat_27_1_1_aar.xml │ ├── Gradle__com_squareup_okhttp3_okhttp_3_8_0_jar.xml │ ├── Gradle__org_hamcrest_hamcrest_core_1_3_jar.xml │ ├── Gradle__com_android_support_support_vector_drawable_27_1_1_aar.xml │ ├── Gradle__org_hamcrest_hamcrest_library_1_3_jar.xml │ ├── Gradle__com_android_support_animated_vector_drawable_27_1_1_aar.xml │ ├── Gradle__com_squareup_retrofit2_retrofit_2_3_0_jar.xml │ ├── Gradle__org_hamcrest_hamcrest_integration_1_3_jar.xml │ ├── Gradle__com_android_support_test_espresso_espresso_idling_resource_3_0_2_aar.xml │ ├── Gradle__com_squareup_retrofit2_converter_gson_2_3_0_jar.xml │ └── Gradle__com_github_bumptech_glide_gifdecoder_4_8_0_aar.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml └── misc.xml ├── local.properties ├── gradle.properties ├── WN.iml ├── WanNeng.iml └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /wnlibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.gradle/4.4/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':wnlibrary' 2 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 27 09:00:52 CST 2018 2 | gradle.version=4.4 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | WN 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gradle/4.4/fileHashes/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/fileHashes/fileHashes.bin -------------------------------------------------------------------------------- /.gradle/4.4/javaCompile/taskJars.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/javaCompile/taskJars.bin -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.gradle/4.4/fileContent/fileContent.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/fileContent/fileContent.lock -------------------------------------------------------------------------------- /.gradle/4.4/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /.gradle/4.4/javaCompile/jarAnalysis.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/javaCompile/jarAnalysis.bin -------------------------------------------------------------------------------- /.gradle/4.4/javaCompile/javaCompile.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/javaCompile/javaCompile.lock -------------------------------------------------------------------------------- /.gradle/4.4/javaCompile/taskHistory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/javaCompile/taskHistory.bin -------------------------------------------------------------------------------- /.gradle/4.4/taskHistory/taskHistory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/taskHistory/taskHistory.bin -------------------------------------------------------------------------------- /.gradle/4.4/taskHistory/taskHistory.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/taskHistory/taskHistory.lock -------------------------------------------------------------------------------- /.gradle/4.4/javaCompile/classAnalysis.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/javaCompile/classAnalysis.bin -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/outputFiles.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/buildOutputCleanup/outputFiles.bin -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gradle/4.4/fileHashes/resourceHashesCache.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/4.4/fileHashes/resourceHashesCache.bin -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/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/wlsj/WanNeng/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/wlsj/WanNeng/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/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlsj/WanNeng/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/subsciber/ProgressCancelListener.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.subsciber; 3 | 4 | /** 5 | *

描述:进度框取消监听

6 | */ 7 | public interface ProgressCancelListener { 8 | void onCancelProgress(); 9 | } 10 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/IType.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.callback; 4 | 5 | import java.lang.reflect.Type; 6 | 7 | /** 8 | *

描述:获取类型接口

9 | */ 10 | public interface IType { 11 | Type getType(); 12 | } 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 23 11:15:24 CST 2018 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-4.4-all.zip 7 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/subsciber/IProgressDialog.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.subsciber; 4 | 5 | import android.app.Dialog; 6 | 7 | /** 8 | *

描述:自定义对话框的dialog

9 | 10 | */ 11 | public interface IProgressDialog { 12 | Dialog getDialog(); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /wnlibrary/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 100dp 5 | 6 | 7 | 20dp 8 | 9 | 10 | 15dp 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/wls/wn/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wls.wn 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class MainActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_main) 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /wnlibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Tue Dec 04 09:20:54 CST 2018 8 | ndk.dir=/Users/WLS/Library/Android/sdk/ndk-bundle 9 | sdk.dir=/Users/WLS/Library/Android/sdk 10 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_google_code_findbugs_jsr305_2_0_1_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/com/wls/wn/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.wls.wn 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/SimpleCallBack.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.callback; 3 | 4 | /** 5 | *

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

6 | * 使用该回调默认只需要处理onError,onSuccess两个方法既成功失败
7 | */ 8 | public abstract class SimpleCallBack extends CallBack { 9 | 10 | @Override 11 | public void onStart() { 12 | } 13 | 14 | @Override 15 | public void onCompleted() { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /wnlibrary/src/main/res/layout/shanglajiazai_weibuju.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/body/ProgressResponseCallBack.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.body; 3 | 4 | /** 5 | *

描述:上传进度回调接口

6 | */ 7 | public interface ProgressResponseCallBack { 8 | /** 9 | * 回调进度 10 | * 11 | * @param bytesWritten 当前读取响应体字节长度 12 | * @param contentLength 总长度 13 | * @param done 是否读取完成 14 | */ 15 | void onResponseProgress(long bytesWritten, long contentLength, boolean done); 16 | } 17 | -------------------------------------------------------------------------------- /wnlibrary/src/test/java/com/wls/wnlibrary/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary; 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() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_constraint_constraint_layout_solver_1_1_2_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /wnlibrary/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__net_sf_kxml_kxml2_2_3_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_constraint_constraint_layout_1_1_2_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__io_reactivex_rxjava2_rxjava_2_1_1_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/func/CacheResultFunc.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.func; 3 | 4 | 5 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 6 | 7 | import io.reactivex.annotations.NonNull; 8 | import io.reactivex.functions.Function; 9 | 10 | /** 11 | *

描述:缓存结果转换

12 | * 作者: zhouyou
13 | * 日期: 2017/4/21 10:53
14 | * 版本: v1.0
15 | */ 16 | public class CacheResultFunc implements Function, T> { 17 | @Override 18 | public T apply(@NonNull CacheResult tCacheResult) throws Exception { 19 | return tCacheResult.data; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_jakewharton_disklrucache_2_0_2_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/exception/ServerException.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.exception; 3 | 4 | /** 5 | *

描述:处理服务器异常

6 | */ 7 | public class ServerException extends RuntimeException { 8 | private int errCode; 9 | private String message; 10 | 11 | public ServerException(int errCode, String msg) { 12 | super(msg); 13 | this.errCode = errCode; 14 | this.message = msg; 15 | } 16 | 17 | public int getErrCode() { 18 | return errCode; 19 | } 20 | 21 | @Override 22 | public String getMessage() { 23 | return message; 24 | } 25 | } -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/DownloadProgressCallBack.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.callback; 3 | 4 | /** 5 | *

描述:下载进度回调(主线程,可以直接操作UI)

6 | */ 7 | public abstract class DownloadProgressCallBack extends CallBack { 8 | public DownloadProgressCallBack() { 9 | } 10 | 11 | @Override 12 | public void onSuccess(T response) { 13 | 14 | } 15 | 16 | public abstract void update(long bytesRead, long contentLength, boolean done); 17 | 18 | public abstract void onComplete(String path); 19 | 20 | @Override 21 | public void onCompleted() { 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_2_30_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_github_bumptech_glide_annotations_4_8_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_github_bumptech_glide_disklrucache_4_8_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_reactivestreams_reactive_streams_1_0_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_retrofit2_adapter_rxjava2_2_3_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_jre7_1_2_30_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_okhttp3_logging_interceptor_3_1_2_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/transformer/HandleErrTransformer.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.transformer; 3 | 4 | 5 | 6 | import com.wls.wnlibrary.utils.net.func.HttpResponseFunc; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.ObservableSource; 10 | import io.reactivex.ObservableTransformer; 11 | import io.reactivex.annotations.NonNull; 12 | 13 | /** 14 | *

描述:错误转换Transformer

15 | */ 16 | public class HandleErrTransformer implements ObservableTransformer { 17 | @Override 18 | public ObservableSource apply(@NonNull Observable upstream) { 19 | return upstream.onErrorResumeNext(new HttpResponseFunc()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_core_runtime_1_1_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__junit_junit_4_12_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/OnlyCacheStrategy.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.stategy; 3 | 4 | import com.wls.wnlibrary.utils.net.cache.RxCache; 5 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 6 | 7 | import java.lang.reflect.Type; 8 | 9 | import io.reactivex.Observable; 10 | 11 | /** 12 | *

描述:只读缓存

13 | *<-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
14 | */ 15 | public final class OnlyCacheStrategy extends BaseStrategy{ 16 | @Override 17 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 18 | return loadCache(rxCache,type,key,time,false); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_design_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_percent_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_test_runner_1_0_2_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_github_bumptech_glide_glide_4_8_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_test_monitor_1_0_2_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__io_reactivex_rxjava2_rxandroid_2_0_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_palette_v7_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_v4_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_transition_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wls/wn/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.wls.wn 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.wls.wn", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_appcompat_v7_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_compat_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_google_code_gson_gson_2_7_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_recyclerview_v7_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_okio_okio_1_13_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__javax_inject_javax_inject_1_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_javawriter_2_1_1_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_test_espresso_espresso_core_3_0_2_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_jetbrains_annotations_13_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_okhttp3_okhttp_3_8_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_support_vector_drawable_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_hamcrest_hamcrest_library_1_3_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_animated_vector_drawable_27_1_1_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_retrofit2_retrofit_2_3_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /wnlibrary/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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/IStrategy.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.stategy; 3 | 4 | 5 | import com.wls.wnlibrary.utils.net.cache.RxCache; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | import io.reactivex.Observable; 11 | 12 | /** 13 | *

描述:实现缓存策略的接口,可以自定义缓存实现方式,只要实现该接口就可以了

14 | */ 15 | public interface IStrategy { 16 | 17 | /** 18 | * 执行缓存 19 | * 20 | * @param rxCache 缓存管理对象 21 | * @param cacheKey 缓存key 22 | * @param cacheTime 缓存时间 23 | * @param source 网络请求对象 24 | * @param type 要转换的目标对象 25 | * @return 返回带缓存的Observable流对象 26 | */ 27 | Observable> execute(RxCache rxCache, String cacheKey, long cacheTime, Observable source, Type type); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/NoCacheInterceptor.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.interceptor; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | 11 | 12 | /** 13 | *

描述:不加载缓存

14 | * 1.不适用Okhttp自带的缓存
15 | */ 16 | public class NoCacheInterceptor implements Interceptor { 17 | @Override 18 | public Response intercept(Chain chain) throws IOException { 19 | Request request = chain.request(); 20 | request = request.newBuilder().header("Cache-Control", "no-cache").build(); 21 | Response originalResponse = chain.proceed(request); 22 | originalResponse = originalResponse.newBuilder().header("Cache-Control", "no-cache").build(); 23 | return originalResponse; 24 | } 25 | } 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__org_hamcrest_hamcrest_integration_1_3_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_android_support_test_espresso_espresso_idling_resource_3_0_2_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_squareup_retrofit2_converter_gson_2_3_0_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /wnlibrary/src/androidTest/java/com/wls/wnlibrary/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.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() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.wls.wnlibrary.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WN.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WanNeng.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/FirstCacheStategy.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.cache.stategy; 4 | 5 | import com.wls.wnlibrary.utils.net.cache.RxCache; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | import io.reactivex.Observable; 11 | 12 | 13 | /** 14 | *

描述:先显示缓存,缓存不存在,再请求网络

15 | * <-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
16 | */ 17 | final public class FirstCacheStategy extends BaseStrategy { 18 | @Override 19 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 20 | Observable> cache = loadCache(rxCache, type, key, time, true); 21 | Observable> remote = loadRemote(rxCache, key, source, false); 22 | return cache.switchIfEmpty(remote); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/pic/TuPianJiaZai.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary.utils.pic; 2 | 3 | /* 4 | * 5 | * wlsj 2018/12/06 6 | * 7 | * */ 8 | 9 | 10 | import android.content.Context; 11 | import android.widget.ImageView; 12 | 13 | import com.bumptech.glide.Glide; 14 | import com.bumptech.glide.request.RequestOptions; 15 | 16 | public class TuPianJiaZai { 17 | 18 | public static void JiaZaiTuPian(Context mContext, String path, int zhanWei, int shiBai, boolean shiFouHuanCun,ImageView mImageView) { 19 | 20 | RequestOptions requestOptions = new RequestOptions() 21 | .placeholder(zhanWei) 22 | .error(shiBai) 23 | .skipMemoryCache(shiFouHuanCun) 24 | ; 25 | 26 | Glide.with(mContext) 27 | .load(path) 28 | .apply(requestOptions) 29 | .into(mImageView); 30 | 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/func/HandleFuc.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.func; 3 | 4 | import com.wls.wnlibrary.utils.net.exception.ApiException; 5 | import com.wls.wnlibrary.utils.net.exception.ServerException; 6 | import com.wls.wnlibrary.utils.net.model.ApiResult; 7 | 8 | import io.reactivex.annotations.NonNull; 9 | import io.reactivex.functions.Function; 10 | 11 | 12 | /** 13 | *

描述:ApiResult转换T

14 | */ 15 | public class HandleFuc implements Function, T> { 16 | @Override 17 | public T apply(@NonNull ApiResult tApiResult) throws Exception { 18 | if (ApiException.isOk(tApiResult)) { 19 | return tApiResult.getData();// == null ? Optional.ofNullable(tApiResult.getData()).orElse(null) : tApiResult.getData(); 20 | } else { 21 | throw new ServerException(tApiResult.getCode(), tApiResult.getMsg()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wnlibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | WNLibrary 3 | MA(5, 10, 20) 4 | ●MA5 %1$.2f ●MA10 %2$.2f ●MA20 %3$.2f 5 | 6 | MACD(12, 26, 9) 7 | MACD(12, 26, 9) ●DIFF %1$.2f ●DEA %2$.2f ●MACD %3$.2f 8 | 9 | RSI(6, 12, 24) 10 | RSI(6, 12, 24) ●RSI1 %1$.2f ●RSI2 %2$.2f ●RSI3 %3$.2f 11 | 12 | KDJ(9, 3, 3) 13 | KDJ(9, 3, 3) ●K %1$.2f ●D %2$.2f ●J %3$.2f 14 | 15 | BOLL(20, 2) 16 | BOLL(20, 2) ●MID %1$.2f ●UPPER %2$.2f ●LOWER %3$.2f 17 | 18 | ●MA5 %1$.2f ●MA10 %2$.2f 19 | 20 | -------------------------------------------------------------------------------- /.idea/libraries/Gradle__com_github_bumptech_glide_gifdecoder_4_8_0_aar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/core/MemoryCache.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.core; 3 | 4 | import java.lang.reflect.Type; 5 | 6 | /** 7 | *

描述:内存缓存

8 | * 内存缓存针对缓存的时间不好处理,暂时没有写内存缓存,等后面有思路了,再加上该部分。
9 | */ 10 | 11 | public class MemoryCache extends BaseCache { 12 | @Override 13 | protected boolean doContainsKey(String key) { 14 | return false; 15 | } 16 | 17 | @Override 18 | protected boolean isExpiry(String key, long existTime) { 19 | return false; 20 | } 21 | 22 | @Override 23 | protected T doLoad(Type type, String key) { 24 | return null; 25 | } 26 | 27 | @Override 28 | protected boolean doSave(String key, T value) { 29 | return false; 30 | } 31 | 32 | @Override 33 | protected boolean doRemove(String key) { 34 | return false; 35 | } 36 | 37 | @Override 38 | protected boolean doClear() { 39 | return false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/converter/IDiskConverter.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.converter; 3 | 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.lang.reflect.Type; 7 | 8 | /** 9 | *

描述:通用转换器接口

10 | * 1.实现该接口可以实现一大波的磁盘存储操作。
11 | * 2.可以实现Serializable、Gson,Parcelable、fastjson、xml、kryo等等
12 | * 目前只实现了:GsonDiskConverter和SerializableDiskConverter转换器,有其它自定义需求自己去实现吧!
13 | *

14 | * 《看到能很方便的实现一大波功能,是不是很刺激啊(*>﹏<*)》
15 | *

16 | */ 17 | public interface IDiskConverter { 18 | 19 | /** 20 | * 读取 21 | * 22 | * @param source 输入流 23 | * @param type 读取数据后要转换的数据类型 24 | * 这里没有用泛型T或者Tyepe来做,是因为本框架决定的一些问题,泛型会丢失 25 | * @return 26 | */ 27 | T load(InputStream source, Type type); 28 | 29 | /** 30 | * 写入 31 | * 32 | * @param sink 33 | * @param data 保存的数据 34 | * @return 35 | */ 36 | boolean writer(OutputStream sink, Object data); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/model/CacheResult.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.model; 3 | 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | *

描述:缓存对象

9 | */ 10 | public class CacheResult implements Serializable { 11 | public boolean isFromCache; 12 | public T data; 13 | 14 | public CacheResult() { 15 | } 16 | 17 | public CacheResult(boolean isFromCache) { 18 | this.isFromCache = isFromCache; 19 | } 20 | 21 | public CacheResult(boolean isFromCache, T data) { 22 | this.isFromCache = isFromCache; 23 | this.data = data; 24 | } 25 | 26 | public boolean isCache() { 27 | return isFromCache; 28 | } 29 | 30 | public void setCache(boolean cache) { 31 | isFromCache = cache; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return "CacheResult{" + 37 | "isCache=" + isFromCache + 38 | ", data=" + data + 39 | '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/model/ApiResult.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.model; 3 | 4 | /** 5 | *

描述:提供的默认的标注返回api

6 | */ 7 | public class ApiResult { 8 | private int code; 9 | private String msg; 10 | private T data; 11 | public int getCode() { 12 | return code; 13 | } 14 | 15 | public void setCode(int code) { 16 | this.code = code; 17 | } 18 | 19 | public String getMsg() { 20 | return msg; 21 | } 22 | 23 | public void setMsg(String msg) { 24 | this.msg = msg; 25 | } 26 | 27 | public T getData() { 28 | return data; 29 | } 30 | 31 | public void setData(T data) { 32 | this.data = data; 33 | } 34 | 35 | public boolean isOk() { 36 | return code == 0; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ApiResult{" + 42 | "code='" + code + '\'' + 43 | ", msg='" + msg + '\'' + 44 | ", data=" + data + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/pic/PaletteTarget.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary.utils.pic; 2 | 3 | import android.support.v4.util.Pair; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class PaletteTarget { 10 | 11 | @BitmapPalette.Profile 12 | protected int paletteProfile = GlidePalette.Profile.VIBRANT; 13 | 14 | protected ArrayList> targetsBackground = new ArrayList<>(); 15 | protected ArrayList> targetsText = new ArrayList<>(); 16 | 17 | protected boolean targetCrossfade = false; 18 | protected int targetCrossfadeSpeed = DEFAULT_CROSSFADE_SPEED; 19 | protected static final int DEFAULT_CROSSFADE_SPEED = 300; 20 | 21 | public PaletteTarget(@BitmapPalette.Profile int paletteProfile) { 22 | this.paletteProfile = paletteProfile; 23 | } 24 | 25 | public void clear() { 26 | targetsBackground.clear(); 27 | targetsText.clear(); 28 | 29 | targetsBackground = null; 30 | targetsText = null; 31 | 32 | targetCrossfade = false; 33 | targetCrossfadeSpeed = DEFAULT_CROSSFADE_SPEED; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 27 9 | defaultConfig { 10 | applicationId "com.wls.wn" 11 | minSdkVersion 15 12 | targetSdkVersion 27 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(include: ['*.jar'], dir: 'libs') 27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 28 | implementation 'com.android.support:appcompat-v7:27.1.1' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 33 | api project(':wnlibrary') 34 | } 35 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/utils/HttpUtil.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.utils; 3 | 4 | import java.nio.charset.Charset; 5 | import java.util.Map; 6 | 7 | /** 8 | *

描述:http工具类

9 | 10 | */ 11 | public class HttpUtil { 12 | public static final Charset UTF8 = Charset.forName("UTF-8"); 13 | public static String createUrlFromParams(String url, Map params) { 14 | try { 15 | StringBuilder sb = new StringBuilder(); 16 | sb.append(url); 17 | if (url.indexOf('&') > 0 || url.indexOf('?') > 0) sb.append("&"); 18 | else sb.append("?"); 19 | for (Map.Entry urlParams : params.entrySet()) { 20 | String urlValues = urlParams.getValue(); 21 | //对参数进行 utf-8 编码,防止头信息传中文 22 | //String urlValue = URLEncoder.encode(urlValues, UTF8.name()); 23 | sb.append(urlParams.getKey()).append("=").append(urlValues).append("&"); 24 | } 25 | sb.deleteCharAt(sb.length() - 1); 26 | return sb.toString(); 27 | } catch (Exception e) { 28 | HttpLog.e(e.getMessage()); 29 | } 30 | return url; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/func/HttpResponseFunc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.func; 18 | 19 | 20 | import com.wls.wnlibrary.utils.net.exception.ApiException; 21 | 22 | import io.reactivex.Observable; 23 | import io.reactivex.annotations.NonNull; 24 | import io.reactivex.functions.Function; 25 | 26 | /** 27 | *

描述:异常转换处理

28 | */ 29 | public class HttpResponseFunc implements Function> { 30 | @Override 31 | public Observable apply(@NonNull Throwable throwable) throws Exception { 32 | return Observable.error(ApiException.handleException(throwable)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/model/CacheMode.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.cache.model; 4 | 5 | /** 6 | *

描述:网络请求策略

7 | */ 8 | public enum CacheMode { 9 | /** 10 | * 不使用缓存,该模式下,cacheKey,cacheMaxAge 参数均无效 11 | **/ 12 | NO_CACHE("NoStrategy"), 13 | /** 14 | * 完全按照HTTP协议的默认缓存规则,走OKhttp的Cache缓存 15 | **/ 16 | DEFAULT("NoStrategy"), 17 | /** 18 | * 先请求网络,请求网络失败后再加载缓存 19 | */ 20 | FIRSTREMOTE("FirstRemoteStrategy"), 21 | 22 | /** 23 | * 先加载缓存,缓存没有再去请求网络 24 | */ 25 | FIRSTCACHE("FirstCacheStategy"), 26 | 27 | /** 28 | * 仅加载网络,但数据依然会被缓存 29 | */ 30 | ONLYREMOTE("OnlyRemoteStrategy"), 31 | 32 | /** 33 | * 只读取缓存 34 | */ 35 | ONLYCACHE("OnlyCacheStrategy"), 36 | 37 | /** 38 | * 先使用缓存,不管是否存在,仍然请求网络,会回调两次 39 | */ 40 | CACHEANDREMOTE("CacheAndRemoteStrategy"), 41 | /** 42 | * 先使用缓存,不管是否存在,仍然请求网络,会先把缓存回调给你, 43 | * 等网络请求回来发现数据是一样的就不会再返回,否则再返回 44 | * (这样做的目的是防止数据是一样的你也需要刷新界面) 45 | */ 46 | CACHEANDREMOTEDISTINCT("CacheAndRemoteDistinctStrategy"); 47 | 48 | private final String className; 49 | 50 | CacheMode(String className) { 51 | this.className = className; 52 | } 53 | 54 | public String getClassName() { 55 | return className; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/CacheAndRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.cache.stategy; 4 | 5 | 6 | import com.wls.wnlibrary.utils.net.cache.RxCache; 7 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 8 | 9 | import java.lang.reflect.Type; 10 | 11 | import io.reactivex.Observable; 12 | import io.reactivex.annotations.NonNull; 13 | import io.reactivex.functions.Predicate; 14 | 15 | 16 | /** 17 | *

描述:先显示缓存,再请求网络

18 | * <-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
19 | */ 20 | public final class CacheAndRemoteStrategy extends BaseStrategy { 21 | @Override 22 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 23 | Observable> cache = loadCache(rxCache, type, key, time, true); 24 | Observable> remote = loadRemote(rxCache, key, source, false); 25 | return Observable.concat(cache, remote) 26 | .filter(new Predicate>() { 27 | @Override 28 | public boolean test(@NonNull CacheResult tCacheResult) throws Exception { 29 | return tCacheResult != null && tCacheResult.data != null; 30 | } 31 | }); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/CallClazzProxy.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.callback; 3 | 4 | import com.google.gson.internal.$Gson$Types; 5 | import com.wls.wnlibrary.utils.net.model.ApiResult; 6 | import com.wls.wnlibrary.utils.net.utils.Utils; 7 | 8 | 9 | import java.lang.reflect.ParameterizedType; 10 | import java.lang.reflect.Type; 11 | 12 | import okhttp3.ResponseBody; 13 | 14 | /** 15 | *

描述:提供Clazz回调代理

16 | * 主要用于可以自定义ApiResult
17 | */ 18 | public abstract class CallClazzProxy, R> implements IType { 19 | private Type type; 20 | 21 | 22 | public CallClazzProxy(Type type) { 23 | this.type = type; 24 | } 25 | 26 | public Type getCallType() { 27 | return type; 28 | } 29 | 30 | @Override 31 | public Type getType() {//CallClazz代理方式,获取需要解析的Type 32 | Type typeArguments = null; 33 | if (type != null) { 34 | typeArguments = type; 35 | } 36 | if (typeArguments == null) { 37 | typeArguments = ResponseBody.class; 38 | } 39 | Type rawType = Utils.findNeedType(getClass()); 40 | if (rawType instanceof ParameterizedType) { 41 | rawType = ((ParameterizedType) rawType).getRawType(); 42 | } 43 | return $Gson$Types.newParameterizedTypeWithOwner(null, rawType, typeArguments); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/OnlyRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.cache.stategy; 18 | 19 | 20 | import com.wls.wnlibrary.utils.net.cache.RxCache; 21 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 22 | 23 | import java.lang.reflect.Type; 24 | 25 | import io.reactivex.Observable; 26 | 27 | /** 28 | *

描述:只请求网络

29 | *<-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
30 | */ 31 | public final class OnlyRemoteStrategy extends BaseStrategy{ 32 | @Override 33 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 34 | return loadRemote(rxCache,key, source,false); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/HeadersInterceptor.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.interceptor; 3 | import com.wls.wnlibrary.utils.net.model.HttpHeaders; 4 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 5 | 6 | import java.io.IOException; 7 | import java.util.Map; 8 | 9 | import okhttp3.Interceptor; 10 | import okhttp3.Request; 11 | import okhttp3.Response; 12 | 13 | /** 14 | *

描述:配置公共头部

15 | */ 16 | public class HeadersInterceptor implements Interceptor { 17 | 18 | private HttpHeaders headers; 19 | 20 | public HeadersInterceptor(HttpHeaders headers) { 21 | this.headers = headers; 22 | } 23 | 24 | 25 | @Override 26 | public Response intercept(Chain chain) throws IOException { 27 | Request.Builder builder = chain.request().newBuilder(); 28 | if (headers.headersMap.isEmpty()) return chain.proceed(builder.build()); 29 | try { 30 | for (Map.Entry entry : headers.headersMap.entrySet()) { 31 | //去除重复的header 32 | //builder.removeHeader(entry.getKey()); 33 | //builder.addHeader(entry.getKey(), entry.getValue()).build(); 34 | builder.header(entry.getKey(), entry.getValue()).build(); 35 | } 36 | } catch (Exception e) { 37 | HttpLog.e(e); 38 | } 39 | return chain.proceed(builder.build()); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/CallBack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.callback; 18 | 19 | 20 | import com.wls.wnlibrary.utils.net.exception.ApiException; 21 | import com.wls.wnlibrary.utils.net.utils.Utils; 22 | 23 | import java.lang.reflect.Type; 24 | 25 | /** 26 | *

描述:网络请求回调

27 | */ 28 | public abstract class CallBack implements IType { 29 | public abstract void onStart(); 30 | 31 | public abstract void onCompleted(); 32 | 33 | public abstract void onError(ApiException e); 34 | 35 | public abstract void onSuccess(T t); 36 | 37 | @Override 38 | public Type getType() {//获取需要解析的泛型T类型 39 | return Utils.findNeedClass(getClass()); 40 | } 41 | 42 | public Type getRawType() {//获取需要解析的泛型T raw类型 43 | return Utils.findRawType(getClass()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/body/RequestBodyUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.body; 3 | 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | import okhttp3.MediaType; 8 | import okhttp3.RequestBody; 9 | import okhttp3.internal.Util; 10 | import okio.BufferedSink; 11 | import okio.Okio; 12 | import okio.Source; 13 | 14 | /** 15 | *

描述:请求体处理工具类

16 | */ 17 | public class RequestBodyUtils { 18 | 19 | //public final static MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); 20 | 21 | public static RequestBody create(final MediaType mediaType, final InputStream inputStream) { 22 | return new RequestBody() { 23 | @Override 24 | public MediaType contentType() { 25 | return mediaType; 26 | } 27 | 28 | @Override 29 | public long contentLength() { 30 | try { 31 | return inputStream.available(); 32 | } catch (IOException e) { 33 | return 0; 34 | } 35 | } 36 | 37 | @Override 38 | public void writeTo(BufferedSink sink) throws IOException { 39 | Source source = null; 40 | try { 41 | source = Okio.source(inputStream); 42 | sink.writeAll(source); 43 | } finally { 44 | Util.closeQuietly(source); 45 | } 46 | } 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/NoStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.cache.stategy; 18 | 19 | import com.wls.wnlibrary.utils.net.cache.RxCache; 20 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 21 | 22 | import java.lang.reflect.Type; 23 | 24 | import io.reactivex.Observable; 25 | import io.reactivex.annotations.NonNull; 26 | import io.reactivex.functions.Function; 27 | 28 | /** 29 | *

描述:网络加载,不缓存

30 | */ 31 | public class NoStrategy implements IStrategy { 32 | @Override 33 | public Observable> execute(RxCache rxCache, String cacheKey, long cacheTime, Observable source, Type type) { 34 | return source.map(new Function>() { 35 | @Override 36 | public CacheResult apply(@NonNull T t) throws Exception { 37 | return new CacheResult(false, t); 38 | } 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/subsciber/CallBackSubsciber.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.subsciber; 4 | 5 | import android.content.Context; 6 | 7 | 8 | import com.wls.wnlibrary.utils.net.callback.CallBack; 9 | import com.wls.wnlibrary.utils.net.callback.ProgressDialogCallBack; 10 | import com.wls.wnlibrary.utils.net.exception.ApiException; 11 | 12 | import io.reactivex.annotations.NonNull; 13 | 14 | 15 | /** 16 | *

描述:带有callBack的回调

17 | * 主要作用是不需要用户订阅,只要实现callback回调
18 | */ 19 | public class CallBackSubsciber extends BaseSubscriber { 20 | public CallBack mCallBack; 21 | 22 | 23 | public CallBackSubsciber(Context context, CallBack callBack) { 24 | super(context); 25 | mCallBack = callBack; 26 | if (callBack instanceof ProgressDialogCallBack) { 27 | ((ProgressDialogCallBack) callBack).subscription(this); 28 | } 29 | } 30 | 31 | 32 | @Override 33 | protected void onStart() { 34 | super.onStart(); 35 | if (mCallBack != null) { 36 | mCallBack.onStart(); 37 | } 38 | } 39 | 40 | @Override 41 | public void onError(ApiException e) { 42 | if (mCallBack != null) { 43 | mCallBack.onError(e); 44 | } 45 | } 46 | 47 | @Override 48 | public void onNext(@NonNull T t) { 49 | super.onNext(t); 50 | if (mCallBack != null) { 51 | mCallBack.onSuccess(t); 52 | } 53 | } 54 | 55 | @Override 56 | public void onComplete() { 57 | super.onComplete(); 58 | if (mCallBack != null) { 59 | mCallBack.onCompleted(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /wnlibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | group='com.github.wlsj' 4 | android { 5 | compileSdkVersion 27 6 | 7 | 8 | 9 | defaultConfig { 10 | minSdkVersion 15 11 | targetSdkVersion 27 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | compile fileTree(include: ['*.jar'], dir: 'libs') 30 | implementation 'com.android.support:appcompat-v7:27.1.1' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 34 | compile 'com.android.support:percent:27.1.1' 35 | compile 'com.squareup.okhttp3:logging-interceptor:3.1.2' 36 | compile 'com.squareup.okhttp3:okhttp:3.4.1' 37 | compile 'com.jakewharton:disklrucache:2.0.2' 38 | compile 'io.reactivex.rxjava2:rxjava:2.1.1' 39 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 40 | compile 'com.squareup.retrofit2:retrofit:2.3.0' 41 | compile 'com.squareup.retrofit2:converter-gson:2.3.0' 42 | compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' 43 | compile 'com.android.support:design:27.1.1' 44 | compile 'com.google.code.gson:gson:2.0.5' 45 | compile 'com.github.bumptech.glide:glide:4.8.0' 46 | compile 'com.android.support:palette-v7:27.1.1' 47 | } 48 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/FirstRemoteStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.cache.stategy; 18 | import com.wls.wnlibrary.utils.net.cache.RxCache; 19 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 20 | 21 | import java.lang.reflect.Type; 22 | import java.util.Arrays; 23 | 24 | import io.reactivex.Observable; 25 | 26 | 27 | /** 28 | *

描述:先请求网络,网络请求失败,再加载缓存

29 | * <-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
30 | */ 31 | public final class FirstRemoteStrategy extends BaseStrategy { 32 | @Override 33 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 34 | Observable> cache = loadCache(rxCache, type, key, time, true); 35 | Observable> remote = loadRemote(rxCache, key, source, false); 36 | //return remote.switchIfEmpty(cache); 37 | return Observable 38 | .concatDelayError(Arrays.asList(remote, cache)) 39 | .take(1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/converter/SerializableDiskConverter.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.converter; 3 | 4 | 5 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 6 | import com.wls.wnlibrary.utils.net.utils.Utils; 7 | 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.ObjectInputStream; 12 | import java.io.ObjectOutputStream; 13 | import java.io.OutputStream; 14 | import java.lang.reflect.Type; 15 | 16 | /** 17 | *

描述:序列化对象的转换器

18 | * 1.使用改转换器,对象&对象中的其它所有对象都必须是要实现Serializable接口(序列化)
19 | * 优点:
20 | * 速度快
21 | * 《-------骚年,自己根据实际需求选择吧!!!------------》
22 | */ 23 | @SuppressWarnings(value={"unchecked", "deprecation"}) 24 | public class SerializableDiskConverter implements IDiskConverter { 25 | 26 | @Override 27 | public T load(InputStream source, Type type) { 28 | //序列化的缓存不需要用到clazz 29 | T value = null; 30 | ObjectInputStream oin = null; 31 | try { 32 | oin = new ObjectInputStream(source); 33 | value = (T) oin.readObject(); 34 | } catch (IOException | ClassNotFoundException e) { 35 | HttpLog.e(e); 36 | } finally { 37 | Utils.close(oin); 38 | } 39 | return value; 40 | } 41 | 42 | @Override 43 | public boolean writer(OutputStream sink, Object data) { 44 | ObjectOutputStream oos = null; 45 | try { 46 | oos = new ObjectOutputStream(sink); 47 | oos.writeObject(data); 48 | oos.flush(); 49 | return true; 50 | } catch (IOException e) { 51 | HttpLog.e(e); 52 | } finally { 53 | Utils.close(oos); 54 | } 55 | return false; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/stategy/CacheAndRemoteDistinctStrategy.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.cache.stategy; 4 | 5 | 6 | 7 | import com.wls.wnlibrary.utils.net.cache.RxCache; 8 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.annotations.NonNull; 14 | import io.reactivex.functions.Function; 15 | import io.reactivex.functions.Predicate; 16 | import okio.ByteString; 17 | 18 | /** 19 | *

描述:先显示缓存,再请求网络

20 | * <-------此类加载用的是反射 所以类名是灰色的 没有直接引用 不要误删---------------->
21 | */ 22 | public final class CacheAndRemoteDistinctStrategy extends BaseStrategy { 23 | @Override 24 | public Observable> execute(RxCache rxCache, String key, long time, Observable source, Type type) { 25 | Observable> cache = loadCache(rxCache, type, key, time,true); 26 | Observable> remote = loadRemote(rxCache, key, source,false); 27 | return Observable.concat(cache, remote) 28 | .filter(new Predicate>() { 29 | @Override 30 | public boolean test(@NonNull CacheResult tCacheResult) throws Exception { 31 | return tCacheResult != null && tCacheResult.data != null; 32 | } 33 | }).distinctUntilChanged(new Function, String>() { 34 | @Override 35 | public String apply(@NonNull CacheResult tCacheResult) throws Exception { 36 | return ByteString.of(tCacheResult.data.toString().getBytes()).md5().hex(); 37 | } 38 | }); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cookie/CookieManger.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cookie; 3 | 4 | import android.content.Context; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import okhttp3.Cookie; 10 | import okhttp3.CookieJar; 11 | import okhttp3.HttpUrl; 12 | 13 | 14 | /** 15 | *

描述:cookie管理器

16 | */ 17 | public class CookieManger implements CookieJar { 18 | 19 | private static Context mContext; 20 | private static PersistentCookieStore cookieStore; 21 | 22 | public CookieManger(Context context) { 23 | mContext = context; 24 | if (cookieStore == null) { 25 | cookieStore = new PersistentCookieStore(mContext); 26 | } 27 | } 28 | 29 | public void addCookies(List cookies) { 30 | cookieStore.addCookies(cookies); 31 | } 32 | 33 | public void saveFromResponse(HttpUrl url, Cookie cookie) { 34 | if (cookie != null) { 35 | cookieStore.add(url, cookie); 36 | } 37 | } 38 | 39 | public PersistentCookieStore getCookieStore() { 40 | return cookieStore; 41 | } 42 | 43 | @Override 44 | public void saveFromResponse(HttpUrl url, List cookies) { 45 | if (cookies != null && cookies.size() > 0) { 46 | for (Cookie item : cookies) { 47 | cookieStore.add(url, item); 48 | } 49 | } 50 | } 51 | 52 | 53 | @Override 54 | public List loadForRequest(HttpUrl url) { 55 | List cookies = cookieStore.get(url); 56 | return cookies != null ? cookies : new ArrayList(); 57 | } 58 | 59 | public void remove(HttpUrl url, Cookie cookie) { 60 | cookieStore.remove(url, cookie); 61 | } 62 | 63 | public void removeAll() { 64 | cookieStore.removeAll(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/CallBackProxy.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.callback; 3 | 4 | import com.google.gson.internal.$Gson$Types; 5 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 6 | import com.wls.wnlibrary.utils.net.model.ApiResult; 7 | import com.wls.wnlibrary.utils.net.utils.Utils; 8 | 9 | import java.lang.reflect.ParameterizedType; 10 | import java.lang.reflect.Type; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import okhttp3.ResponseBody; 15 | 16 | /** 17 | *

描述:提供回调代理

18 | * 主要用于可以自定义ApiResult
19 | */ 20 | public abstract class CallBackProxy, R> implements IType { 21 | CallBack mCallBack; 22 | 23 | public CallBackProxy(CallBack callBack) { 24 | mCallBack = callBack; 25 | } 26 | 27 | public CallBack getCallBack() { 28 | return mCallBack; 29 | } 30 | 31 | @Override 32 | public Type getType() {//CallBack代理方式,获取需要解析的Type 33 | Type typeArguments = null; 34 | if (mCallBack != null) { 35 | Type rawType = mCallBack.getRawType();//如果用户的信息是返回List需单独处理 36 | if (List.class.isAssignableFrom(Utils.getClass(rawType, 0)) || Map.class.isAssignableFrom(Utils.getClass(rawType, 0))) { 37 | typeArguments = mCallBack.getType(); 38 | } else if (CacheResult.class.isAssignableFrom(Utils.getClass(rawType, 0))) { 39 | Type type = mCallBack.getType(); 40 | typeArguments = Utils.getParameterizedType(type, 0); 41 | } else { 42 | Type type = mCallBack.getType(); 43 | typeArguments = Utils.getClass(type, 0); 44 | } 45 | } 46 | if (typeArguments == null) { 47 | typeArguments = ResponseBody.class; 48 | } 49 | Type rawType = Utils.findNeedType(getClass()); 50 | if (rawType instanceof ParameterizedType) { 51 | rawType = ((ParameterizedType) rawType).getRawType(); 52 | } 53 | return $Gson$Types.newParameterizedTypeWithOwner(null, rawType, typeArguments); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/subsciber/BaseSubscriber.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.subsciber; 4 | 5 | import android.content.Context; 6 | 7 | 8 | import com.wls.wnlibrary.utils.net.exception.ApiException; 9 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 10 | 11 | import java.lang.ref.WeakReference; 12 | 13 | import io.reactivex.annotations.NonNull; 14 | import io.reactivex.observers.DisposableObserver; 15 | 16 | import static com.wls.wnlibrary.utils.net.utils.Utils.isNetworkAvailable; 17 | 18 | /** 19 | *

描述:订阅的基类

20 | * 1.可以防止内存泄露。
21 | * 2.在onStart()没有网络时直接onCompleted();
22 | * 3.统一处理了异常
23 | 24 | */ 25 | public abstract class BaseSubscriber extends DisposableObserver { 26 | public WeakReference contextWeakReference; 27 | 28 | public BaseSubscriber() { 29 | } 30 | 31 | @Override 32 | protected void onStart() { 33 | HttpLog.e("-->http is onStart"); 34 | if (contextWeakReference != null && contextWeakReference.get() != null && !isNetworkAvailable(contextWeakReference.get())) { 35 | //Toast.makeText(context, "无网络,读取缓存数据", Toast.LENGTH_SHORT).show(); 36 | onComplete(); 37 | } 38 | } 39 | 40 | 41 | public BaseSubscriber(Context context) { 42 | if (context != null) { 43 | contextWeakReference = new WeakReference<>(context); 44 | } 45 | } 46 | 47 | @Override 48 | public void onNext(@NonNull T t) { 49 | HttpLog.e("-->http is onNext"); 50 | } 51 | 52 | @Override 53 | public final void onError(Throwable e) { 54 | HttpLog.e("-->http is onError"); 55 | if (e instanceof ApiException) { 56 | HttpLog.e("--> e instanceof ApiException err:" + e); 57 | onError((ApiException) e); 58 | } else { 59 | HttpLog.e("--> e !instanceof ApiException err:" + e); 60 | onError(ApiException.handleException(e)); 61 | } 62 | } 63 | 64 | @Override 65 | public void onComplete() { 66 | HttpLog.e("-->http is onComplete"); 67 | } 68 | 69 | 70 | public abstract void onError(ApiException e); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cookie/SerializableOkHttpCookies.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cookie; 3 | 4 | import java.io.IOException; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | import java.io.Serializable; 8 | 9 | import okhttp3.Cookie; 10 | 11 | /** 12 | *

描述:对存储的cookie进行序列化

13 | */ 14 | public class SerializableOkHttpCookies implements Serializable { 15 | 16 | private transient final Cookie cookies; 17 | private transient Cookie clientCookies; 18 | 19 | public SerializableOkHttpCookies(Cookie cookies) { 20 | this.cookies = cookies; 21 | } 22 | 23 | public Cookie getCookies() { 24 | Cookie bestCookies = cookies; 25 | if (clientCookies != null) { 26 | bestCookies = clientCookies; 27 | } 28 | return bestCookies; 29 | } 30 | 31 | private void writeObject(ObjectOutputStream out) throws IOException { 32 | out.writeObject(cookies.name()); 33 | out.writeObject(cookies.value()); 34 | out.writeLong(cookies.expiresAt()); 35 | out.writeObject(cookies.domain()); 36 | out.writeObject(cookies.path()); 37 | out.writeBoolean(cookies.secure()); 38 | out.writeBoolean(cookies.httpOnly()); 39 | out.writeBoolean(cookies.hostOnly()); 40 | out.writeBoolean(cookies.persistent()); 41 | } 42 | 43 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 44 | String name = (String) in.readObject(); 45 | String value = (String) in.readObject(); 46 | long expiresAt = in.readLong(); 47 | String domain = (String) in.readObject(); 48 | String path = (String) in.readObject(); 49 | boolean secure = in.readBoolean(); 50 | boolean httpOnly = in.readBoolean(); 51 | boolean hostOnly = in.readBoolean(); 52 | //boolean persistent = in.readBoolean(); 53 | Cookie.Builder builder = new Cookie.Builder(); 54 | builder = builder.name(name); 55 | builder = builder.value(value); 56 | builder = builder.expiresAt(expiresAt); 57 | builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain); 58 | builder = builder.path(path); 59 | builder = secure ? builder.secure() : builder; 60 | builder = httpOnly ? builder.httpOnly() : builder; 61 | clientCookies =builder.build(); 62 | } 63 | } -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/CacheInterceptor.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.interceptor; 3 | 4 | import android.content.Context; 5 | import android.text.TextUtils; 6 | 7 | 8 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 9 | 10 | import java.io.IOException; 11 | 12 | import okhttp3.Interceptor; 13 | import okhttp3.Response; 14 | 15 | /** 16 | *

描述:设置缓存功能

17 | */ 18 | public class CacheInterceptor implements Interceptor { 19 | 20 | protected Context context; 21 | protected String cacheControlValue_Offline; 22 | protected String cacheControlValue_Online; 23 | //set cahe times is 3 days 24 | protected static final int maxStale = 60 * 60 * 24 * 3; 25 | // read from cache for 60 s 26 | protected static final int maxStaleOnline = 60; 27 | 28 | public CacheInterceptor(Context context) { 29 | this(context, String.format("max-age=%d", maxStaleOnline)); 30 | } 31 | 32 | public CacheInterceptor(Context context, String cacheControlValue) { 33 | this(context, cacheControlValue, String.format("max-age=%d", maxStale)); 34 | } 35 | 36 | public CacheInterceptor(Context context, String cacheControlValueOffline, String cacheControlValueOnline) { 37 | this.context = context; 38 | this.cacheControlValue_Offline = cacheControlValueOffline; 39 | this.cacheControlValue_Online = cacheControlValueOnline; 40 | } 41 | 42 | @Override 43 | public Response intercept(Chain chain) throws IOException { 44 | //Request request = chain.request(); 45 | Response originalResponse = chain.proceed(chain.request()); 46 | String cacheControl = originalResponse.header("Cache-Control"); 47 | //String cacheControl = request.cacheControl().toString(); 48 | HttpLog.e( maxStaleOnline + "s load cache:" + cacheControl); 49 | if (TextUtils.isEmpty(cacheControl) || cacheControl.contains("no-store") || cacheControl.contains("no-cache") || 50 | cacheControl.contains("must-revalidate") || cacheControl.contains("max-age") || cacheControl.contains("max-stale")) { 51 | return originalResponse.newBuilder() 52 | .removeHeader("Pragma") 53 | .removeHeader("Cache-Control") 54 | .header("Cache-Control", "public, max-age=" + maxStale) 55 | .build(); 56 | 57 | } else { 58 | return originalResponse; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/JsonJieXi.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary.utils.net; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.reflect.TypeToken; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public class JsonJieXi { 10 | private static Gson gson = null; 11 | 12 | static { 13 | if (gson == null) { 14 | gson = new Gson(); 15 | } 16 | } 17 | 18 | private JsonJieXi() { 19 | } 20 | 21 | /** 22 | * 转成json 23 | * 24 | * @param object 25 | * @return 26 | */ 27 | public static String GsonString(Object object) { 28 | String gsonString = null; 29 | if (gson != null) { 30 | gsonString = gson.toJson(object); 31 | } 32 | return gsonString; 33 | } 34 | 35 | /** 36 | * 转成bean 37 | * 38 | * @param gsonString 39 | * @param cls 40 | * @return 41 | */ 42 | public static T GsonToBean(String gsonString, Class cls) { 43 | T t = null; 44 | if (gson != null) { 45 | t = gson.fromJson(gsonString, cls); 46 | } 47 | return t; 48 | } 49 | 50 | /** 51 | * 转成list 52 | * 53 | * @param gsonString 54 | * @param cls 55 | * @return 56 | */ 57 | public static List GsonToList(String gsonString, Class cls) { 58 | List list = null; 59 | if (gson != null) { 60 | list = gson.fromJson(gsonString, new TypeToken>() { 61 | }.getType()); 62 | } 63 | return list; 64 | } 65 | 66 | /** 67 | * 转成list中有map的 68 | * 69 | * @param gsonString 70 | * @return 71 | */ 72 | public static List> GsonToListMaps(String gsonString) { 73 | List> list = null; 74 | if (gson != null) { 75 | list = gson.fromJson(gsonString, 76 | new TypeToken>>() { 77 | }.getType()); 78 | } 79 | return list; 80 | } 81 | 82 | /** 83 | * 转成map的 84 | * 85 | * @param gsonString 86 | * @return 87 | */ 88 | public static Map GsonToMaps(String gsonString) { 89 | Map map = null; 90 | if (gson != null) { 91 | map = gson.fromJson(gsonString, new TypeToken>() { 92 | }.getType()); 93 | } 94 | return map; 95 | } 96 | } -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/BaseExpiredInterceptor.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.interceptor; 3 | 4 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 5 | 6 | import java.io.IOException; 7 | import java.nio.charset.Charset; 8 | 9 | import okhttp3.Interceptor; 10 | import okhttp3.MediaType; 11 | import okhttp3.Request; 12 | import okhttp3.Response; 13 | import okhttp3.ResponseBody; 14 | import okio.Buffer; 15 | import okio.BufferedSource; 16 | 17 | import static com.wls.wnlibrary.utils.net.utils.HttpUtil.UTF8; 18 | 19 | /** 20 | *

描述:判断响应是否有效的处理

21 | * 继承后扩展各种无效响应处理:包括token过期、账号异地登录、时间戳过期、签名sign错误等
22 | */ 23 | public abstract class BaseExpiredInterceptor implements Interceptor { 24 | @Override 25 | public Response intercept(Chain chain) throws IOException { 26 | Request request = chain.request(); 27 | Response response = chain.proceed(request); 28 | ResponseBody responseBody = response.body(); 29 | BufferedSource source = responseBody.source(); 30 | source.request(Long.MAX_VALUE); // Buffer the entire body. 31 | Buffer buffer = source.buffer(); 32 | Charset charset = UTF8; 33 | MediaType contentType = responseBody.contentType(); 34 | if (contentType != null) { 35 | charset = contentType.charset(UTF8); 36 | } 37 | String bodyString = buffer.clone().readString(charset); 38 | HttpLog.i("网络拦截器:" + bodyString + " host:" + request.url().toString()); 39 | boolean isText = isText(contentType); 40 | if (!isText) { 41 | return response; 42 | } 43 | //判断响应是否过期(无效) 44 | if (isResponseExpired(response, bodyString)) { 45 | return responseExpired(chain, bodyString); 46 | } 47 | return response; 48 | } 49 | 50 | private boolean isText(MediaType mediaType) { 51 | if (mediaType == null) 52 | return false; 53 | if (mediaType.type() != null && mediaType.type().equals("text")) { 54 | return true; 55 | } 56 | if (mediaType.subtype() != null) { 57 | if (mediaType.subtype().equals("json")) { 58 | return true; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | /** 65 | * 处理响应是否有效 66 | */ 67 | public abstract boolean isResponseExpired(Response response, String bodyString); 68 | 69 | /** 70 | * 无效响应处理 71 | */ 72 | public abstract Response responseExpired(Chain chain, String bodyString); 73 | } 74 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/GzipRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.interceptor; 18 | 19 | import java.io.IOException; 20 | 21 | import okhttp3.Interceptor; 22 | import okhttp3.MediaType; 23 | import okhttp3.Request; 24 | import okhttp3.RequestBody; 25 | import okhttp3.Response; 26 | import okio.BufferedSink; 27 | import okio.GzipSink; 28 | import okio.Okio; 29 | 30 | /** 31 | *

描述:post数据进行gzip后发送给服务器

32 | * okhttp内部默认启用了gzip,此选项是针对需要对post数据进行gzip后发送给服务器的,如服务器不支持,请勿开启
33 | */ 34 | public class GzipRequestInterceptor implements Interceptor { 35 | @Override 36 | public Response intercept(Chain chain) throws IOException { 37 | Request originalRequest = chain.request(); 38 | if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { 39 | return chain.proceed(originalRequest); 40 | } 41 | Request compressedRequest = originalRequest.newBuilder() 42 | .header("Accept-Encoding", "gzip") 43 | .method(originalRequest.method(), gzip(originalRequest.body())) 44 | .build(); 45 | return chain.proceed(compressedRequest); 46 | } 47 | 48 | private RequestBody gzip(final RequestBody body) { 49 | return new RequestBody() { 50 | @Override 51 | public MediaType contentType() { 52 | return body.contentType(); 53 | } 54 | 55 | @Override 56 | public long contentLength() { 57 | return -1; 58 | } 59 | 60 | @Override 61 | public void writeTo(BufferedSink sink) throws IOException { 62 | BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); 63 | body.writeTo(gzipSink); 64 | gzipSink.close(); 65 | } 66 | }; 67 | } 68 | } -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/DownloadRequest.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.request; 4 | 5 | 6 | 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 9 | import com.wls.wnlibrary.utils.net.subsciber.DownloadSubscriber; 10 | import com.wls.wnlibrary.utils.net.transformer.HandleErrTransformer; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.ObservableSource; 14 | import io.reactivex.ObservableTransformer; 15 | import io.reactivex.annotations.NonNull; 16 | import io.reactivex.disposables.Disposable; 17 | import io.reactivex.schedulers.Schedulers; 18 | import okhttp3.ResponseBody; 19 | 20 | /** 21 | *

描述:下载请求

22 | 23 | */ 24 | @SuppressWarnings(value={"unchecked", "deprecation"}) 25 | public class DownloadRequest extends BaseRequest { 26 | public DownloadRequest(String url) { 27 | super(url); 28 | } 29 | 30 | private String savePath; 31 | private String saveName; 32 | 33 | /** 34 | * 下载文件路径
35 | * 默认在:/storage/emulated/0/Android/data/包名/files/1494647767055
36 | */ 37 | public DownloadRequest savePath(String savePath) { 38 | this.savePath = savePath; 39 | return this; 40 | } 41 | 42 | /** 43 | * 下载文件名称
44 | * 默认名字是时间戳生成的
45 | */ 46 | public DownloadRequest saveName(String saveName) { 47 | this.saveName = saveName; 48 | return this; 49 | } 50 | 51 | public Disposable execute(CallBack callBack) { 52 | return (Disposable) build().generateRequest().compose(new ObservableTransformer() { 53 | @Override 54 | public ObservableSource apply(@NonNull Observable upstream) { 55 | if (isSyncRequest) { 56 | return upstream;//.observeOn(AndroidSchedulers.mainThread()); 57 | } else { 58 | return upstream.subscribeOn(Schedulers.io()) 59 | .unsubscribeOn(Schedulers.io()) 60 | .observeOn(Schedulers.computation()); 61 | } 62 | } 63 | }).compose(new HandleErrTransformer()).retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)) 64 | .subscribeWith(new DownloadSubscriber(context, savePath, saveName, callBack)); 65 | } 66 | 67 | @Override 68 | protected Observable generateRequest() { 69 | return apiManager.downloadFile(url); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/core/CacheCore.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.core; 3 | 4 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 5 | import com.wls.wnlibrary.utils.net.utils.Utils; 6 | 7 | import java.lang.reflect.Type; 8 | 9 | import okio.ByteString; 10 | 11 | /** 12 | *

描述:缓存核心管理类

13 | *

14 | * 1.采用LruDiskCache
15 | * 2.对Key进行MD5加密
16 | *

17 | * 以后可以扩展 增加内存缓存,但是内存缓存的时间不好控制,暂未实现,后续可以添加》
18 | *

19 | *

20 | * 1.这里笔者给读者留个提醒,ByteString其实已经很强大了,不需要我们自己再去处理加密了,只要善于发现br> 21 | * 2.这里为设么把MD5改成ByteString呢?其实改不改无所谓,只是想把ByteString这个好东西介绍给大家。(ok)br> 22 | * 3.在ByteString中有很多好用的方法包括MD5.sha1 base64 encodeUtf8 等等功能。br> 23 | */ 24 | public class CacheCore { 25 | 26 | private LruDiskCache disk; 27 | 28 | public CacheCore(LruDiskCache disk) { 29 | this.disk = Utils.checkNotNull(disk, "disk==null"); 30 | } 31 | 32 | 33 | /** 34 | * 读取 35 | */ 36 | public synchronized T load(Type type, String key, long time) { 37 | String cacheKey = ByteString.of(key.getBytes()).md5().hex(); 38 | HttpLog.d("loadCache key=" + cacheKey); 39 | if (disk != null) { 40 | T result = disk.load(type, cacheKey, time); 41 | if (result != null) { 42 | return result; 43 | } 44 | } 45 | 46 | return null; 47 | } 48 | 49 | /** 50 | * 保存 51 | */ 52 | public synchronized boolean save(String key, T value) { 53 | String cacheKey = ByteString.of(key.getBytes()).md5().hex(); 54 | HttpLog.d("saveCache key=" + cacheKey); 55 | return disk.save(cacheKey, value); 56 | } 57 | 58 | /** 59 | * 是否包含 60 | * 61 | * @param key 62 | * @return 63 | */ 64 | public synchronized boolean containsKey(String key) { 65 | String cacheKey = ByteString.of(key.getBytes()).md5().hex(); 66 | HttpLog.d("containsCache key=" + cacheKey); 67 | if (disk != null) { 68 | if (disk.containsKey(cacheKey)) { 69 | return true; 70 | } 71 | } 72 | return false; 73 | } 74 | 75 | /** 76 | * 删除缓存 77 | * 78 | * @param key 79 | */ 80 | public synchronized boolean remove(String key) { 81 | String cacheKey = ByteString.of(key.getBytes()).md5().hex(); 82 | HttpLog.d("removeCache key=" + cacheKey); 83 | if (disk != null) { 84 | return disk.remove(cacheKey); 85 | } 86 | return true; 87 | } 88 | 89 | /** 90 | * 清空缓存 91 | */ 92 | public synchronized boolean clear() { 93 | if (disk != null) { 94 | return disk.clear(); 95 | } 96 | return false; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/converter/GsonDiskConverter.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.converter; 3 | 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.JsonIOException; 7 | import com.google.gson.JsonSyntaxException; 8 | import com.google.gson.TypeAdapter; 9 | import com.google.gson.reflect.TypeToken; 10 | import com.google.gson.stream.JsonReader; 11 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 12 | import com.wls.wnlibrary.utils.net.utils.Utils; 13 | 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.InputStreamReader; 18 | import java.io.OutputStream; 19 | import java.lang.reflect.Type; 20 | import java.util.ConcurrentModificationException; 21 | 22 | /** 23 | *

描述:GSON-数据转换器

24 | * 1.GSON-数据转换器其实就是存储字符串的操作
25 | * 2.如果你的Gson有特殊处理,可以自己创建一个,否则用默认。
26 | *

27 | * 优点:
28 | * 相对于SerializableDiskConverter转换器,存储的对象不需要进行序列化(Serializable),
29 | * 特别是一个对象中又包含很多其它对象,每个对象都需要Serializable,比较麻烦
30 | *

31 | *

32 | *

33 | * 缺点:
34 | * 就是存储和读取都要使用Gson进行转换,object->String->Object的给一个过程,相对来说
35 | * 每次都要转换性能略低,但是以现在的手机性能可以忽略不计了。
36 | *

37 | *

38 | * 《-------骚年,自己根据实际需求选择吧!!!------------》
39 | * 《--看到这里,顺便提下知道IDiskConverter的好处了吧,面向接口编程是不是很灵活(*^_^*)----------》
40 | *

41 | */ 42 | @SuppressWarnings(value={"unchecked", "deprecation"}) 43 | public class GsonDiskConverter implements IDiskConverter { 44 | private Gson gson = new Gson(); 45 | 46 | public GsonDiskConverter() { 47 | this.gson = new Gson(); 48 | } 49 | 50 | public GsonDiskConverter(Gson gson) { 51 | Utils.checkNotNull(gson, "gson ==null"); 52 | this.gson = gson; 53 | } 54 | 55 | @Override 56 | public T load(InputStream source, Type type) { 57 | T value = null; 58 | try { 59 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); 60 | JsonReader jsonReader = gson.newJsonReader(new InputStreamReader(source)); 61 | value = (T) adapter.read(jsonReader); 62 | //value = gson.fromJson(new InputStreamReader(source), type); 63 | } catch (JsonIOException | IOException| ConcurrentModificationException | JsonSyntaxException e) { 64 | HttpLog.e(e.getMessage()); 65 | } catch (Exception e){ 66 | HttpLog.e(e.getMessage()); 67 | }finally { 68 | Utils.close(source); 69 | } 70 | return value; 71 | } 72 | 73 | @Override 74 | public boolean writer(OutputStream sink, Object data) { 75 | try { 76 | String json = gson.toJson(data); 77 | byte[] bytes = json.getBytes(); 78 | sink.write(bytes, 0, bytes.length); 79 | sink.flush(); 80 | return true; 81 | } catch (JsonIOException | JsonSyntaxException | ConcurrentModificationException| IOException e) { 82 | HttpLog.e(e.getMessage()); 83 | }catch (Exception e){ 84 | HttpLog.e(e.getMessage()); 85 | } finally { 86 | Utils.close(sink); 87 | } 88 | return false; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/body/UploadProgressRequestBody.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.body; 3 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 4 | import java.io.IOException; 5 | import okhttp3.MediaType; 6 | import okhttp3.RequestBody; 7 | import okio.Buffer; 8 | import okio.BufferedSink; 9 | import okio.ForwardingSink; 10 | import okio.Okio; 11 | import okio.Sink; 12 | 13 | /** 14 | *

描述:上传请求体

15 | * 1.具有上传进度回调通知功能
16 | * 2.防止频繁回调,上层无用的刷新
17 | */ 18 | public class UploadProgressRequestBody extends RequestBody { 19 | 20 | protected RequestBody delegate; 21 | protected ProgressResponseCallBack progressCallBack; 22 | 23 | protected CountingSink countingSink; 24 | 25 | public UploadProgressRequestBody(ProgressResponseCallBack listener) { 26 | this.progressCallBack = listener; 27 | } 28 | 29 | public UploadProgressRequestBody(RequestBody delegate, ProgressResponseCallBack progressCallBack) { 30 | this.delegate = delegate; 31 | this.progressCallBack = progressCallBack; 32 | } 33 | 34 | public void setRequestBody(RequestBody delegate) { 35 | this.delegate = delegate; 36 | } 37 | 38 | @Override 39 | public MediaType contentType() { 40 | return delegate.contentType(); 41 | 42 | } 43 | 44 | /** 45 | * 重写调用实际的响应体的contentLength 46 | */ 47 | @Override 48 | public long contentLength() { 49 | try { 50 | return delegate.contentLength(); 51 | } catch (IOException e) { 52 | HttpLog.e(e.getMessage()); 53 | return -1; 54 | } 55 | } 56 | 57 | @Override 58 | public void writeTo(BufferedSink sink) throws IOException { 59 | BufferedSink bufferedSink; 60 | 61 | countingSink = new CountingSink(sink); 62 | bufferedSink = Okio.buffer(countingSink); 63 | 64 | delegate.writeTo(bufferedSink); 65 | 66 | bufferedSink.flush(); 67 | } 68 | 69 | 70 | protected final class CountingSink extends ForwardingSink { 71 | private long bytesWritten = 0; 72 | private long contentLength = 0; //总字节长度,避免多次调用contentLength()方法 73 | private long lastRefreshUiTime; //最后一次刷新的时间 74 | 75 | public CountingSink(Sink delegate) { 76 | super(delegate); 77 | } 78 | 79 | @Override 80 | public void write(Buffer source, long byteCount) throws IOException { 81 | super.write(source, byteCount); 82 | if (contentLength <= 0) contentLength = contentLength(); //获得contentLength的值,后续不再调用 83 | //增加当前写入的字节数 84 | bytesWritten += byteCount; 85 | 86 | long curTime = System.currentTimeMillis(); 87 | //每100毫秒刷新一次数据,防止频繁无用的刷新 88 | if (curTime - lastRefreshUiTime >= 100 || bytesWritten == contentLength) { 89 | progressCallBack.onResponseProgress(bytesWritten, contentLength, bytesWritten == contentLength); 90 | lastRefreshUiTime = System.currentTimeMillis(); 91 | } 92 | HttpLog.i("bytesWritten=" + bytesWritten + " ,totalBytesCount=" + contentLength); 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/interceptor/CacheInterceptorOffline.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.interceptor; 18 | 19 | import android.content.Context; 20 | 21 | 22 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 23 | import com.wls.wnlibrary.utils.net.utils.Utils; 24 | 25 | import java.io.IOException; 26 | 27 | import okhttp3.CacheControl; 28 | import okhttp3.Request; 29 | import okhttp3.Response; 30 | 31 | /** 32 | *

描述:支持离线缓存,使用OKhttp自带的缓存功能

33 | * 34 | * 配置Okhttp的Cache
35 | * 配置请求头中的cache-control或者统一处理所有请求的请求头
36 | * 云端配合设置响应头或者自己写拦截器修改响应头中cache-control
37 | * 列:
38 | *

39 | * 在Retrofit中,我们可以通过@Headers来配置,如: 40 | * 41 | * @Headers("Cache-Control: public, max-age=3600) 42 | * @GET("merchants/{shopId}/icon") 43 | * Observable getShopIcon(@Path("shopId") long shopId); 44 | * 45 | * 如果你不想加入公共缓存,想单独对某个api进行缓存,可用Headers来实现
46 | * 47 | * 请参考网址:http://www.jianshu.com/p/9c3b4ea108a7
48 | *

49 | * 日期: 2016/12/19 16:35
50 | * 版本: v2.0
51 | */ 52 | public class CacheInterceptorOffline extends CacheInterceptor { 53 | public CacheInterceptorOffline(Context context) { 54 | super(context); 55 | } 56 | 57 | public CacheInterceptorOffline(Context context, String cacheControlValue) { 58 | super(context, cacheControlValue); 59 | } 60 | 61 | public CacheInterceptorOffline(Context context, String cacheControlValue, String cacheOnlineControlValue) { 62 | super(context, cacheControlValue, cacheOnlineControlValue); 63 | } 64 | 65 | @Override 66 | public Response intercept(Chain chain) throws IOException { 67 | Request request = chain.request(); 68 | if (!Utils.isNetworkAvailable(context)) { 69 | HttpLog.i(" no network load cache:"+ request.cacheControl().toString()); 70 | /* request = request.newBuilder() 71 | .removeHeader("Pragma") 72 | .header("Cache-Control", "only-if-cached, " + cacheControlValue_Offline) 73 | .build();*/ 74 | 75 | request = request.newBuilder() 76 | .cacheControl(CacheControl.FORCE_CACHE) 77 | //.cacheControl(CacheControl.FORCE_NETWORK) 78 | .build(); 79 | Response response = chain.proceed(request); 80 | return response.newBuilder() 81 | .removeHeader("Pragma") 82 | .removeHeader("Cache-Control") 83 | .header("Cache-Control", "public, only-if-cached, " + cacheControlValue_Offline) 84 | .build(); 85 | } 86 | return chain.proceed(request); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/DeleteRequest.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.request; 4 | 5 | import com.google.gson.reflect.TypeToken; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.callback.CallBackProxy; 9 | import com.wls.wnlibrary.utils.net.func.ApiResultFunc; 10 | import com.wls.wnlibrary.utils.net.func.CacheResultFunc; 11 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 12 | import com.wls.wnlibrary.utils.net.model.ApiResult; 13 | import com.wls.wnlibrary.utils.net.subsciber.CallBackSubsciber; 14 | import com.wls.wnlibrary.utils.net.utils.RxUtil; 15 | 16 | 17 | import io.reactivex.Observable; 18 | import io.reactivex.ObservableSource; 19 | import io.reactivex.ObservableTransformer; 20 | import io.reactivex.annotations.NonNull; 21 | import io.reactivex.disposables.Disposable; 22 | import okhttp3.RequestBody; 23 | import okhttp3.ResponseBody; 24 | 25 | /** 26 | *

描述:删除请求

27 | */ 28 | @SuppressWarnings(value = {"unchecked", "deprecation"}) 29 | public class DeleteRequest extends BaseBodyRequest { 30 | public DeleteRequest(String url) { 31 | super(url); 32 | } 33 | 34 | public Disposable execute(CallBack callBack) { 35 | return execute(new CallBackProxy, T>(callBack) { 36 | }); 37 | } 38 | 39 | public Disposable execute(CallBackProxy, T> proxy) { 40 | Observable> observable = build().toObservable(generateRequest(), proxy); 41 | if (CacheResult.class != proxy.getCallBack().getRawType()) { 42 | return observable.compose(new ObservableTransformer, T>() { 43 | @Override 44 | public ObservableSource apply(@NonNull Observable> upstream) { 45 | return upstream.map(new CacheResultFunc()); 46 | } 47 | }).subscribeWith(new CallBackSubsciber(context, proxy.getCallBack())); 48 | } else { 49 | return observable.subscribeWith(new CallBackSubsciber>(context, proxy.getCallBack())); 50 | } 51 | } 52 | 53 | private Observable> toObservable(Observable observable, CallBackProxy, T> proxy) { 54 | return observable.map(new ApiResultFunc(proxy != null ? proxy.getType() : new TypeToken() { 55 | }.getType())) 56 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 57 | .compose(rxCache.transformer(cacheMode, proxy.getCallBack().getType())) 58 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 59 | } 60 | 61 | @Override 62 | protected Observable generateRequest() { 63 | if (this.requestBody != null) { //自定义的请求体 64 | return apiManager.deleteBody(url, this.requestBody); 65 | } else if (this.json != null) {//Json 66 | RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), this.json); 67 | return apiManager.deleteJson(url, body); 68 | } else if (this.object != null) {//自定义的请求object 69 | return apiManager.deleteBody(url, object); 70 | } else if (this.string != null) {//文本内容 71 | RequestBody body = RequestBody.create(mediaType, this.string); 72 | return apiManager.deleteBody(url, body); 73 | } else { 74 | return apiManager.delete(url, params.urlParamsMap); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/core/BaseCache.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.core; 3 | 4 | 5 | import com.wls.wnlibrary.utils.net.utils.Utils; 6 | 7 | import java.lang.reflect.Type; 8 | import java.util.concurrent.locks.ReadWriteLock; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock; 10 | 11 | /** 12 | *

描述:缓存的基类

13 | * 1.所有缓存处理都继承该基类
14 | * 2.增加了锁机制,防止频繁读取缓存造成的异常。
15 | * 3.子类直接考虑具体的实现细节就可以了。
16 | *

17 | */ 18 | public abstract class BaseCache { 19 | private final ReadWriteLock mLock = new ReentrantReadWriteLock(); 20 | 21 | /** 22 | * 读取缓存 23 | * 24 | * @param key 缓存key 25 | * @param existTime 缓存时间 26 | */ 27 | final T load(Type type, String key, long existTime) { 28 | //1.先检查key 29 | Utils.checkNotNull(key, "key == null"); 30 | 31 | //2.判断key是否存在,key不存在去读缓存没意义 32 | if (!containsKey(key)) { 33 | return null; 34 | } 35 | 36 | //3.判断是否过期,过期自动清理 37 | if (isExpiry(key, existTime)) { 38 | remove(key); 39 | return null; 40 | } 41 | 42 | //4.开始真正的读取缓存 43 | mLock.readLock().lock(); 44 | try { 45 | // 读取缓存 46 | return doLoad(type, key); 47 | } finally { 48 | mLock.readLock().unlock(); 49 | } 50 | } 51 | 52 | /** 53 | * 保存缓存 54 | * 55 | * @param key 缓存key 56 | * @param value 缓存内容 57 | * @return 58 | */ 59 | final boolean save(String key, T value) { 60 | //1.先检查key 61 | Utils.checkNotNull(key, "key == null"); 62 | 63 | //2.如果要保存的值为空,则删除 64 | if (value == null) { 65 | return remove(key); 66 | } 67 | 68 | //3.写入缓存 69 | boolean status = false; 70 | mLock.writeLock().lock(); 71 | try { 72 | status = doSave(key, value); 73 | } finally { 74 | mLock.writeLock().unlock(); 75 | } 76 | return status; 77 | } 78 | 79 | /** 80 | * 删除缓存 81 | */ 82 | final boolean remove(String key) { 83 | mLock.writeLock().lock(); 84 | try { 85 | return doRemove(key); 86 | } finally { 87 | mLock.writeLock().unlock(); 88 | } 89 | } 90 | 91 | /** 92 | * 清空缓存 93 | */ 94 | final boolean clear() { 95 | mLock.writeLock().lock(); 96 | try { 97 | return doClear(); 98 | } finally { 99 | mLock.writeLock().unlock(); 100 | } 101 | } 102 | 103 | /** 104 | * 是否包含 加final 是让子类不能被重写,只能使用doContainsKey
105 | * 这里加了锁处理,操作安全。
106 | * 107 | * @param key 缓存key 108 | * @return 是否有缓存 109 | */ 110 | public final boolean containsKey(String key) { 111 | mLock.readLock().lock(); 112 | try { 113 | return doContainsKey(key); 114 | } finally { 115 | mLock.readLock().unlock(); 116 | } 117 | } 118 | 119 | /** 120 | * 是否包含 采用protected修饰符 被子类修改 121 | */ 122 | protected abstract boolean doContainsKey(String key); 123 | 124 | /** 125 | * 是否过期 126 | */ 127 | protected abstract boolean isExpiry(String key, long existTime); 128 | 129 | /** 130 | * 读取缓存 131 | */ 132 | protected abstract T doLoad(Type type, String key); 133 | 134 | /** 135 | * 保存 136 | */ 137 | protected abstract boolean doSave(String key, T value); 138 | 139 | /** 140 | * 删除缓存 141 | */ 142 | protected abstract boolean doRemove(String key); 143 | 144 | /** 145 | * 清空缓存 146 | */ 147 | protected abstract boolean doClear(); 148 | } 149 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/PostRequest.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.request; 3 | 4 | 5 | import com.google.gson.reflect.TypeToken; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.callback.CallBackProxy; 9 | import com.wls.wnlibrary.utils.net.callback.CallClazzProxy; 10 | import com.wls.wnlibrary.utils.net.func.ApiResultFunc; 11 | import com.wls.wnlibrary.utils.net.func.CacheResultFunc; 12 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 13 | import com.wls.wnlibrary.utils.net.model.ApiResult; 14 | import com.wls.wnlibrary.utils.net.subsciber.CallBackSubsciber; 15 | import com.wls.wnlibrary.utils.net.utils.RxUtil; 16 | 17 | 18 | import java.lang.reflect.Type; 19 | 20 | import io.reactivex.Observable; 21 | import io.reactivex.ObservableSource; 22 | import io.reactivex.ObservableTransformer; 23 | import io.reactivex.annotations.NonNull; 24 | import io.reactivex.disposables.Disposable; 25 | import okhttp3.ResponseBody; 26 | 27 | /** 28 | *

描述:post请求

29 | */ 30 | @SuppressWarnings(value={"unchecked", "deprecation"}) 31 | public class PostRequest extends BaseBodyRequest { 32 | public PostRequest(String url) { 33 | super(url); 34 | } 35 | 36 | public Observable execute(Class clazz) { 37 | return execute(new CallClazzProxy, T>(clazz) { 38 | }); 39 | } 40 | 41 | public Observable execute(Type type) { 42 | return execute(new CallClazzProxy, T>(type) { 43 | }); 44 | } 45 | 46 | public Observable execute(CallClazzProxy, T> proxy) { 47 | return build().generateRequest() 48 | .map(new ApiResultFunc(proxy.getType())) 49 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 50 | .compose(rxCache.transformer(cacheMode, proxy.getCallType())) 51 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)) 52 | .compose(new ObservableTransformer() { 53 | @Override 54 | public ObservableSource apply(@NonNull Observable upstream) { 55 | return upstream.map(new CacheResultFunc()); 56 | } 57 | }); 58 | } 59 | 60 | public Disposable execute(CallBack callBack) { 61 | return execute(new CallBackProxy, T>(callBack) { 62 | }); 63 | } 64 | 65 | public Disposable execute(CallBackProxy, T> proxy) { 66 | Observable> observable = build().toObservable(generateRequest(), proxy); 67 | if (CacheResult.class != proxy.getCallBack().getRawType()) { 68 | return observable.compose(new ObservableTransformer, T>() { 69 | @Override 70 | public ObservableSource apply(@NonNull Observable> upstream) { 71 | return upstream.map(new CacheResultFunc()); 72 | } 73 | }).subscribeWith(new CallBackSubsciber(context, proxy.getCallBack())); 74 | } else { 75 | return observable.subscribeWith(new CallBackSubsciber>(context, proxy.getCallBack())); 76 | } 77 | } 78 | 79 | private Observable> toObservable(Observable observable, CallBackProxy, T> proxy) { 80 | return observable.map(new ApiResultFunc(proxy != null ? proxy.getType() : new TypeToken() { 81 | }.getType())) 82 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 83 | .compose(rxCache.transformer(cacheMode, proxy.getCallBack().getType())) 84 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/api/ApiService.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.api; 3 | 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import io.reactivex.Observable; 8 | import okhttp3.MultipartBody; 9 | import okhttp3.RequestBody; 10 | import okhttp3.ResponseBody; 11 | import retrofit2.http.Body; 12 | import retrofit2.http.DELETE; 13 | import retrofit2.http.FieldMap; 14 | import retrofit2.http.FormUrlEncoded; 15 | import retrofit2.http.GET; 16 | import retrofit2.http.HTTP; 17 | import retrofit2.http.Headers; 18 | import retrofit2.http.Multipart; 19 | import retrofit2.http.POST; 20 | import retrofit2.http.PUT; 21 | import retrofit2.http.Part; 22 | import retrofit2.http.PartMap; 23 | import retrofit2.http.QueryMap; 24 | import retrofit2.http.Streaming; 25 | import retrofit2.http.Url; 26 | 27 | /** 28 | *

描述:通用的的api接口

29 | *

30 | * 1.加入基础API,减少Api冗余
31 | * 2.支持多种方式访问网络(get,put,post,delete),包含了常用的情况
32 | * 3.传统的Retrofit用法,服务器每增加一个接口,就要对应一个api,非常繁琐
33 | * 4.如果返回ResponseBody在返回的结果中去获取T,又会报错,这是因为在运行过程中,通过泛型传入的类型T丢失了,所以无法转换,这叫做泛型擦除。 34 | * 《泛型擦除》不知道的童鞋自己百度哦!!
35 | *

36 | *

37 | * 注意事项:
38 | * 1.使用@url,而不是@Path注解,后者放到方法体上,会强制先urlencode,然后与baseurl拼接,请求无法成功
39 | * 2.注意事项: map不能为null,否则该请求不会执行,但可以size为空.
40 | *

41 | * 作者: zhouyou
42 | * 日期: 2016/12/19 16:35
43 | * 版本: v2.0
44 | */ 45 | public interface ApiService { 46 | 47 | @POST() 48 | @FormUrlEncoded 49 | Observable post(@Url String url, @FieldMap Map maps); 50 | 51 | @POST() 52 | Observable postBody(@Url String url, @Body Object object); 53 | 54 | @POST() 55 | @Headers({"Content-Type: application/json", "Accept: application/json"}) 56 | Observable postJson(@Url String url, @Body RequestBody jsonBody); 57 | 58 | @POST() 59 | Observable postBody(@Url String url, @Body RequestBody body); 60 | 61 | @GET() 62 | Observable get(@Url String url, @QueryMap Map maps); 63 | 64 | @DELETE() 65 | Observable delete(@Url String url, @QueryMap Map maps); 66 | 67 | //@DELETE()//delete body请求比较特殊 需要自定义 68 | @HTTP(method = "DELETE",/*path = "",*/hasBody = true) 69 | Observable deleteBody(@Url String url, @Body Object object); 70 | 71 | //@DELETE()//delete body请求比较特殊 需要自定义 72 | @HTTP(method = "DELETE",/*path = "",*/hasBody = true) 73 | Observable deleteBody(@Url String url, @Body RequestBody body); 74 | 75 | //@DELETE()//delete body请求比较特殊 需要自定义 76 | @Headers({"Content-Type: application/json", "Accept: application/json"}) 77 | @HTTP(method = "DELETE",/*path = "",*/hasBody = true) 78 | Observable deleteJson(@Url String url, @Body RequestBody jsonBody); 79 | 80 | @PUT() 81 | Observable put(@Url String url, @QueryMap Map maps); 82 | 83 | @PUT() 84 | Observable putBody(@Url String url, @Body Object object); 85 | 86 | @PUT() 87 | Observable putBody(@Url String url, @Body RequestBody body); 88 | 89 | @PUT() 90 | @Headers({"Content-Type: application/json", "Accept: application/json"}) 91 | Observable putJson(@Url String url, @Body RequestBody jsonBody); 92 | 93 | @Multipart 94 | @POST() 95 | Observable uploadFlie(@Url String fileUrl, @Part("description") RequestBody description, @Part("files") MultipartBody.Part file); 96 | 97 | @Multipart 98 | @POST() 99 | Observable uploadFiles(@Url String url, @PartMap() Map maps); 100 | 101 | @Multipart 102 | @POST() 103 | Observable uploadFiles(@Url String url, @Part() List parts); 104 | 105 | @Streaming 106 | @GET 107 | Observable downloadFile(@Url String fileUrl); 108 | } 109 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/GetRequest.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.request; 3 | 4 | 5 | import com.google.gson.reflect.TypeToken; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.callback.CallBackProxy; 9 | import com.wls.wnlibrary.utils.net.callback.CallClazzProxy; 10 | import com.wls.wnlibrary.utils.net.func.ApiResultFunc; 11 | import com.wls.wnlibrary.utils.net.func.CacheResultFunc; 12 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 13 | import com.wls.wnlibrary.utils.net.model.ApiResult; 14 | import com.wls.wnlibrary.utils.net.subsciber.CallBackSubsciber; 15 | import com.wls.wnlibrary.utils.net.utils.RxUtil; 16 | 17 | 18 | import java.lang.reflect.Type; 19 | 20 | import io.reactivex.Observable; 21 | import io.reactivex.ObservableSource; 22 | import io.reactivex.ObservableTransformer; 23 | import io.reactivex.annotations.NonNull; 24 | import io.reactivex.disposables.Disposable; 25 | import okhttp3.ResponseBody; 26 | 27 | /** 28 | *

描述:get请求

29 | */ 30 | @SuppressWarnings(value={"unchecked", "deprecation"}) 31 | public class GetRequest extends BaseRequest { 32 | public GetRequest(String url) { 33 | super(url); 34 | } 35 | 36 | public Observable execute(Class clazz) { 37 | return execute(new CallClazzProxy, T>(clazz) { 38 | }); 39 | } 40 | 41 | public Observable execute(Type type) { 42 | return execute(new CallClazzProxy, T>(type) { 43 | }); 44 | } 45 | 46 | public Observable execute(CallClazzProxy, T> proxy) { 47 | return build().generateRequest() 48 | .map(new ApiResultFunc(proxy.getType())) 49 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 50 | .compose(rxCache.transformer(cacheMode, proxy.getCallType())) 51 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)) 52 | .compose(new ObservableTransformer() { 53 | @Override 54 | public ObservableSource apply(@NonNull Observable upstream) { 55 | return upstream.map(new CacheResultFunc()); 56 | } 57 | }); 58 | } 59 | 60 | public Disposable execute(CallBack callBack) { 61 | return execute(new CallBackProxy, T>(callBack) { 62 | }); 63 | } 64 | 65 | public Disposable execute(CallBackProxy, T> proxy) { 66 | Observable> observable = build().toObservable(apiManager.get(url, params.urlParamsMap), proxy); 67 | if (CacheResult.class != proxy.getCallBack().getRawType()) { 68 | return observable.compose(new ObservableTransformer, T>() { 69 | @Override 70 | public ObservableSource apply(@NonNull Observable> upstream) { 71 | return upstream.map(new CacheResultFunc()); 72 | } 73 | }).subscribeWith(new CallBackSubsciber(context, proxy.getCallBack())); 74 | } else { 75 | return observable.subscribeWith(new CallBackSubsciber>(context, proxy.getCallBack())); 76 | } 77 | } 78 | 79 | private Observable> toObservable(Observable observable, CallBackProxy, T> proxy) { 80 | return observable.map(new ApiResultFunc(proxy != null ? proxy.getType() : new TypeToken() { 81 | }.getType())) 82 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 83 | .compose(rxCache.transformer(cacheMode, proxy.getCallBack().getType())) 84 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 85 | } 86 | 87 | @Override 88 | protected Observable generateRequest() { 89 | return apiManager.get(url, params.urlParamsMap); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/subsciber/ProgressSubscriber.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.subsciber; 4 | 5 | import android.app.Dialog; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | 9 | import com.wls.wnlibrary.utils.net.exception.ApiException; 10 | 11 | 12 | /** 13 | *

描述: 实现带有进度的订阅

14 | *

15 | * 1.支持自定义加载进度框
16 | * 2.支持对话框取消时可以自动终止本次请求,取消订阅。
17 | * 修改内容:支持自定义对话框
18 | 19 | */ 20 | public abstract class ProgressSubscriber extends BaseSubscriber implements ProgressCancelListener { 21 | private IProgressDialog progressDialog; 22 | private Dialog mDialog; 23 | private boolean isShowProgress = true; 24 | 25 | 26 | /** 27 | * 默认不显示弹出框,不可以取消 28 | * 29 | * @param context 上下文 30 | */ 31 | public ProgressSubscriber(Context context) { 32 | super(context); 33 | init(false); 34 | } 35 | 36 | /** 37 | * 自定义加载进度框 38 | * 39 | * @param context 上下文 40 | * @param progressDialog 自定义对话框 41 | */ 42 | public ProgressSubscriber(Context context, IProgressDialog progressDialog) { 43 | super(context); 44 | this.progressDialog = progressDialog; 45 | init(false); 46 | } 47 | 48 | /** 49 | * 自定义加载进度框,可以设置是否显示弹出框,是否可以取消 50 | * 51 | * @param context 上下文 52 | * @param progressDialog 对话框 53 | * @param isShowProgress 是否显示对话框 54 | * @param isCancel 对话框是否可以取消 55 | */ 56 | public ProgressSubscriber(Context context, IProgressDialog progressDialog, boolean isShowProgress, boolean isCancel) { 57 | super(context); 58 | this.progressDialog = progressDialog; 59 | this.isShowProgress = isShowProgress; 60 | init(isCancel); 61 | } 62 | 63 | /** 64 | * 初始化 65 | * 66 | * @param isCancel 对话框是否可以取消 67 | */ 68 | private void init(boolean isCancel) { 69 | if (progressDialog == null) return; 70 | mDialog = progressDialog.getDialog(); 71 | if (mDialog == null) return; 72 | mDialog.setCancelable(isCancel); 73 | if (isCancel) { 74 | mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 75 | @Override 76 | public void onCancel(DialogInterface dialogInterface) { 77 | ProgressSubscriber.this.onCancelProgress(); 78 | } 79 | }); 80 | } 81 | } 82 | 83 | /** 84 | * 展示进度框 85 | */ 86 | private void showProgress() { 87 | if (!isShowProgress) { 88 | return; 89 | } 90 | if (mDialog != null) { 91 | if (!mDialog.isShowing()) { 92 | mDialog.show(); 93 | } 94 | } 95 | } 96 | 97 | /** 98 | * 取消进度框 99 | */ 100 | private void dismissProgress() { 101 | if (!isShowProgress) { 102 | return; 103 | } 104 | if (mDialog != null) { 105 | if (mDialog.isShowing()) { 106 | mDialog.dismiss(); 107 | } 108 | } 109 | } 110 | 111 | @Override 112 | public void onStart() { 113 | showProgress(); 114 | } 115 | 116 | @Override 117 | public void onComplete() { 118 | dismissProgress(); 119 | } 120 | 121 | @Override 122 | public void onError(ApiException e) { 123 | dismissProgress(); 124 | //int errCode = e.getCode(); 125 | /*if (errCode == ApiException.ERROR.TIMEOUT_ERROR) { 126 | ToastUtil.showToast(contextWeakReference.get(), "网络中断,请检查您的网络状态"); 127 | } else if (errCode == ApiException.ERROR.NETWORD_ERROR) { 128 | ToastUtil.showToast(contextWeakReference.get(), "请检查您的网络状态"); 129 | } else { 130 | ToastUtil.showToast(contextWeakReference.get(), "error:" + e.getMessage()); 131 | }*/ 132 | } 133 | 134 | @Override 135 | public void onCancelProgress() { 136 | if (!isDisposed()) { 137 | dispose(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/callback/ProgressDialogCallBack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.callback; 18 | 19 | import android.app.Dialog; 20 | import android.content.DialogInterface; 21 | 22 | 23 | import com.wls.wnlibrary.utils.net.exception.ApiException; 24 | import com.wls.wnlibrary.utils.net.subsciber.IProgressDialog; 25 | import com.wls.wnlibrary.utils.net.subsciber.ProgressCancelListener; 26 | 27 | import io.reactivex.disposables.Disposable; 28 | 29 | /** 30 | *

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

31 | * 1.可以自定义带有加载进度框的回调,是否需要显示,是否可以取消
32 | * 2.取消对话框会自动取消掉网络请求
33 | 34 | */ 35 | public abstract class ProgressDialogCallBack extends CallBack implements ProgressCancelListener { 36 | private IProgressDialog progressDialog; 37 | private Dialog mDialog; 38 | private boolean isShowProgress = true; 39 | 40 | public ProgressDialogCallBack(IProgressDialog progressDialog) { 41 | this.progressDialog = progressDialog; 42 | init(false); 43 | } 44 | 45 | /** 46 | * 自定义加载进度框,可以设置是否显示弹出框,是否可以取消 47 | * 48 | * @param progressDialog dialog 49 | * @param isShowProgress 是否显示进度 50 | * @param isCancel 对话框是否可以取消 51 | */ 52 | public ProgressDialogCallBack(IProgressDialog progressDialog, boolean isShowProgress, boolean isCancel) { 53 | this.progressDialog = progressDialog; 54 | this.isShowProgress = isShowProgress; 55 | init(isCancel); 56 | } 57 | 58 | /** 59 | * 初始化 60 | * 61 | * @param isCancel 62 | */ 63 | private void init(boolean isCancel) { 64 | if (progressDialog == null) return; 65 | mDialog = progressDialog.getDialog(); 66 | if (mDialog == null) return; 67 | mDialog.setCancelable(isCancel); 68 | if (isCancel) { 69 | mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 70 | @Override 71 | public void onCancel(DialogInterface dialogInterface) { 72 | ProgressDialogCallBack.this.onCancelProgress(); 73 | } 74 | }); 75 | } 76 | } 77 | 78 | /** 79 | * 展示进度框 80 | */ 81 | private void showProgress() { 82 | if (!isShowProgress) { 83 | return; 84 | } 85 | if (mDialog != null) { 86 | if (!mDialog.isShowing()) { 87 | mDialog.show(); 88 | } 89 | } 90 | } 91 | 92 | /** 93 | * 取消进度框 94 | */ 95 | private void dismissProgress() { 96 | if (!isShowProgress) { 97 | return; 98 | } 99 | if (mDialog != null) { 100 | if (mDialog.isShowing()) { 101 | mDialog.dismiss(); 102 | } 103 | } 104 | } 105 | 106 | @Override 107 | public void onStart() { 108 | showProgress(); 109 | } 110 | 111 | @Override 112 | public void onCompleted() { 113 | dismissProgress(); 114 | } 115 | 116 | @Override 117 | public void onError(ApiException e) { 118 | dismissProgress(); 119 | } 120 | 121 | @Override 122 | public void onCancelProgress() { 123 | if (disposed != null && !disposed.isDisposed()) { 124 | disposed.dispose(); 125 | } 126 | } 127 | 128 | private Disposable disposed; 129 | 130 | public void subscription(Disposable disposed) { 131 | this.disposed = disposed; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/func/RetryExceptionFunc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 zhouyou(478319399@qq.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wls.wnlibrary.utils.net.func; 18 | 19 | 20 | 21 | import com.wls.wnlibrary.utils.net.exception.ApiException; 22 | import com.wls.wnlibrary.utils.net.utils.HttpLog; 23 | 24 | import java.net.ConnectException; 25 | import java.net.SocketTimeoutException; 26 | import java.util.concurrent.TimeUnit; 27 | import java.util.concurrent.TimeoutException; 28 | 29 | import io.reactivex.Observable; 30 | import io.reactivex.ObservableSource; 31 | import io.reactivex.annotations.NonNull; 32 | import io.reactivex.functions.BiFunction; 33 | import io.reactivex.functions.Function; 34 | 35 | /** 36 | *

描述:网络请求错误重试条件

37 | */ 38 | public class RetryExceptionFunc implements Function, Observable> { 39 | /* retry次数*/ 40 | private int count = 0; 41 | /*延迟*/ 42 | private long delay = 500; 43 | /*叠加延迟*/ 44 | private long increaseDelay = 3000; 45 | 46 | public RetryExceptionFunc() { 47 | 48 | } 49 | 50 | public RetryExceptionFunc(int count, long delay) { 51 | this.count = count; 52 | this.delay = delay; 53 | } 54 | 55 | public RetryExceptionFunc(int count, long delay, long increaseDelay) { 56 | this.count = count; 57 | this.delay = delay; 58 | this.increaseDelay = increaseDelay; 59 | } 60 | 61 | @Override 62 | public Observable apply(@NonNull Observable observable) throws Exception { 63 | return observable.zipWith(Observable.range(1, count + 1), new BiFunction() { 64 | @Override 65 | public Wrapper apply(@NonNull Throwable throwable, @NonNull Integer integer) throws Exception { 66 | return new Wrapper(throwable, integer); 67 | } 68 | }).flatMap(new Function>() { 69 | @Override 70 | public ObservableSource apply(@NonNull Wrapper wrapper) throws Exception { 71 | if (wrapper.index > 1) 72 | HttpLog.i("重试次数:" + (wrapper.index)); 73 | int errCode = 0; 74 | if (wrapper.throwable instanceof ApiException) { 75 | ApiException exception = (ApiException) wrapper.throwable; 76 | errCode = exception.getCode(); 77 | } 78 | if ((wrapper.throwable instanceof ConnectException 79 | || wrapper.throwable instanceof SocketTimeoutException 80 | || errCode == ApiException.ERROR.NETWORD_ERROR 81 | || errCode == ApiException.ERROR.TIMEOUT_ERROR 82 | || wrapper.throwable instanceof SocketTimeoutException 83 | || wrapper.throwable instanceof TimeoutException) 84 | && wrapper.index < count + 1) { //如果超出重试次数也抛出错误,否则默认是会进入onCompleted 85 | return Observable.timer(delay + (wrapper.index - 1) * increaseDelay, TimeUnit.MILLISECONDS); 86 | 87 | } 88 | return Observable.error(wrapper.throwable); 89 | } 90 | }); 91 | } 92 | 93 | private class Wrapper { 94 | private int index; 95 | private Throwable throwable; 96 | 97 | public Wrapper(Throwable throwable, int index) { 98 | this.index = index; 99 | this.throwable = throwable; 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/body/UIProgressResponseCallBack.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.body; 3 | 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.os.Message; 7 | 8 | import java.io.Serializable; 9 | import java.lang.ref.WeakReference; 10 | 11 | /** 12 | *

描述:可以直接更新UI的回调

13 | */ 14 | public abstract class UIProgressResponseCallBack implements ProgressResponseCallBack { 15 | private static final int RESPONSE_UPDATE = 0x02; 16 | 17 | //处理UI层的Handler子类 18 | private static class UIHandler extends Handler { 19 | //弱引用 20 | private final WeakReference mUIProgressResponseListenerWeakReference; 21 | 22 | public UIHandler(Looper looper, UIProgressResponseCallBack uiProgressResponseListener) { 23 | super(looper); 24 | mUIProgressResponseListenerWeakReference = new WeakReference(uiProgressResponseListener); 25 | } 26 | 27 | @Override 28 | public void handleMessage(Message msg) { 29 | switch (msg.what) { 30 | case RESPONSE_UPDATE: 31 | UIProgressResponseCallBack uiProgressResponseListener = mUIProgressResponseListenerWeakReference.get(); 32 | if (uiProgressResponseListener != null) { 33 | //获得进度实体类 34 | ProgressModel progressModel = (ProgressModel) msg.obj; 35 | //回调抽象方法 36 | uiProgressResponseListener.onUIResponseProgress(progressModel.getCurrentBytes(), progressModel.getContentLength(), progressModel.isDone()); 37 | } 38 | break; 39 | default: 40 | super.handleMessage(msg); 41 | break; 42 | } 43 | } 44 | } 45 | 46 | //主线程Handler 47 | private final Handler mHandler = new UIHandler(Looper.getMainLooper(), this); 48 | 49 | @Override 50 | public void onResponseProgress(long bytesWritten, long contentLength, boolean done) { 51 | //通过Handler发送进度消息 52 | Message message = Message.obtain(); 53 | message.obj = new ProgressModel(bytesWritten, contentLength, done); 54 | message.what = RESPONSE_UPDATE; 55 | mHandler.sendMessage(message); 56 | } 57 | 58 | /** 59 | * UI层回调抽象方法 60 | * 61 | * @param bytesRead 当前读取响应体字节长度 62 | * @param contentLength 总字节长度 63 | * @param done 是否读取完成 64 | */ 65 | public abstract void onUIResponseProgress(long bytesRead, long contentLength, boolean done); 66 | 67 | public class ProgressModel implements Serializable { 68 | //当前读取字节长度 69 | private long currentBytes; 70 | //总字节长度 71 | private long contentLength; 72 | //是否读取完成 73 | private boolean done; 74 | 75 | public ProgressModel(long currentBytes, long contentLength, boolean done) { 76 | this.currentBytes = currentBytes; 77 | this.contentLength = contentLength; 78 | this.done = done; 79 | } 80 | 81 | public long getCurrentBytes() { 82 | return currentBytes; 83 | } 84 | 85 | public ProgressModel setCurrentBytes(long currentBytes) { 86 | this.currentBytes = currentBytes; 87 | return this; 88 | } 89 | 90 | public long getContentLength() { 91 | return contentLength; 92 | } 93 | 94 | public ProgressModel setContentLength(long contentLength) { 95 | this.contentLength = contentLength; 96 | return this; 97 | } 98 | 99 | public boolean isDone() { 100 | return done; 101 | } 102 | 103 | public ProgressModel setDone(boolean done) { 104 | this.done = done; 105 | return this; 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "ProgressModel{" + 111 | "currentBytes=" + currentBytes + 112 | ", contentLength=" + contentLength + 113 | ", done=" + done + 114 | '}'; 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/utils/RxUtil.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.utils; 4 | 5 | 6 | 7 | import com.wls.wnlibrary.utils.net.func.HandleFuc; 8 | import com.wls.wnlibrary.utils.net.func.HttpResponseFunc; 9 | import com.wls.wnlibrary.utils.net.model.ApiResult; 10 | 11 | import io.reactivex.Observable; 12 | import io.reactivex.ObservableSource; 13 | import io.reactivex.ObservableTransformer; 14 | import io.reactivex.android.schedulers.AndroidSchedulers; 15 | import io.reactivex.annotations.NonNull; 16 | import io.reactivex.disposables.Disposable; 17 | import io.reactivex.functions.Action; 18 | import io.reactivex.functions.Consumer; 19 | import io.reactivex.schedulers.Schedulers; 20 | 21 | 22 | /** 23 | *

描述:线程调度工具

24 | */ 25 | public class RxUtil { 26 | 27 | public static ObservableTransformer io_main() { 28 | return new ObservableTransformer() { 29 | @Override 30 | public ObservableSource apply(@NonNull Observable upstream) { 31 | return upstream 32 | .subscribeOn(Schedulers.io()) 33 | .unsubscribeOn(Schedulers.io()) 34 | .doOnSubscribe(new Consumer() { 35 | @Override 36 | public void accept(@NonNull Disposable disposable) throws Exception { 37 | HttpLog.i("+++doOnSubscribe+++" + disposable.isDisposed()); 38 | } 39 | }) 40 | .doFinally(new Action() { 41 | @Override 42 | public void run() throws Exception { 43 | HttpLog.i("+++doFinally+++"); 44 | } 45 | }) 46 | .observeOn(AndroidSchedulers.mainThread()); 47 | } 48 | }; 49 | } 50 | 51 | public static ObservableTransformer, T> _io_main() { 52 | return new ObservableTransformer, T>() { 53 | @Override 54 | public ObservableSource apply(@NonNull Observable> upstream) { 55 | return upstream 56 | .subscribeOn(Schedulers.io()) 57 | .unsubscribeOn(Schedulers.io()) 58 | .observeOn(AndroidSchedulers.mainThread()) 59 | .map(new HandleFuc()) 60 | .doOnSubscribe(new Consumer() { 61 | @Override 62 | public void accept(@NonNull Disposable disposable) throws Exception { 63 | HttpLog.i("+++doOnSubscribe+++" + disposable.isDisposed()); 64 | } 65 | }) 66 | .doFinally(new Action() { 67 | @Override 68 | public void run() throws Exception { 69 | HttpLog.i("+++doFinally+++"); 70 | } 71 | }) 72 | .onErrorResumeNext(new HttpResponseFunc()); 73 | } 74 | }; 75 | } 76 | 77 | 78 | public static ObservableTransformer, T> _main() { 79 | return new ObservableTransformer, T>() { 80 | @Override 81 | public ObservableSource apply(@NonNull Observable> upstream) { 82 | return upstream 83 | //.observeOn(AndroidSchedulers.mainThread()) 84 | .map(new HandleFuc()) 85 | .doOnSubscribe(new Consumer() { 86 | @Override 87 | public void accept(@NonNull Disposable disposable) throws Exception { 88 | HttpLog.i("+++doOnSubscribe+++" + disposable.isDisposed()); 89 | } 90 | }) 91 | .doFinally(new Action() { 92 | @Override 93 | public void run() throws Exception { 94 | HttpLog.i("+++doFinally+++"); 95 | } 96 | }) 97 | .onErrorResumeNext(new HttpResponseFunc()); 98 | } 99 | }; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/pic/GlidePalette.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary.utils.pic; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.BitmapDrawable; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.annotation.Nullable; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import com.bumptech.glide.load.DataSource; 11 | import com.bumptech.glide.load.engine.GlideException; 12 | import com.bumptech.glide.load.resource.gif.GifDrawable; 13 | import com.bumptech.glide.request.RequestListener; 14 | import com.bumptech.glide.request.target.Target; 15 | 16 | public class GlidePalette extends BitmapPalette implements RequestListener { 17 | 18 | protected RequestListener callback; 19 | 20 | protected GlidePalette() { 21 | } 22 | 23 | public static GlidePalette with(String url) { 24 | GlidePalette glidePalette = new GlidePalette<>(); 25 | glidePalette.url = url; 26 | return glidePalette; 27 | } 28 | 29 | @SuppressWarnings("unchecked") 30 | public GlidePalette asGif() { 31 | return (GlidePalette) this; 32 | } 33 | 34 | public GlidePalette use(@Profile int paletteProfile) { 35 | super.use(paletteProfile); 36 | return this; 37 | } 38 | 39 | public GlidePalette intoBackground(View view) { 40 | return this.intoBackground(view, Swatch.RGB); 41 | } 42 | 43 | @Override 44 | public GlidePalette intoBackground(View view, @Swatch int paletteSwatch) { 45 | super.intoBackground(view, paletteSwatch); 46 | return this; 47 | } 48 | 49 | public GlidePalette intoTextColor(TextView textView) { 50 | return this.intoTextColor(textView, Swatch.TITLE_TEXT_COLOR); 51 | } 52 | 53 | @Override 54 | public GlidePalette intoTextColor(TextView textView, @Swatch int paletteSwatch) { 55 | super.intoTextColor(textView, paletteSwatch); 56 | return this; 57 | } 58 | 59 | @Override 60 | public GlidePalette crossfade(boolean crossfade) { 61 | super.crossfade(crossfade); 62 | return this; 63 | } 64 | 65 | @Override 66 | public GlidePalette crossfade(boolean crossfade, int crossfadeSpeed) { 67 | super.crossfade(crossfade, crossfadeSpeed); 68 | return this; 69 | } 70 | 71 | public GlidePalette setGlideListener(RequestListener listener) { 72 | this.callback = listener; 73 | return this; 74 | } 75 | 76 | @Override 77 | public GlidePalette intoCallBack(GlidePalette.CallBack callBack) { 78 | super.intoCallBack(callBack); 79 | return this; 80 | } 81 | 82 | @Override 83 | public GlidePalette setPaletteBuilderInterceptor(PaletteBuilderInterceptor interceptor) { 84 | super.setPaletteBuilderInterceptor(interceptor); 85 | return this; 86 | } 87 | 88 | @Override 89 | public GlidePalette skipPaletteCache(boolean skipCache) { 90 | super.skipPaletteCache(skipCache); 91 | return this; 92 | } 93 | 94 | @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { 95 | return this.callback != null && this.callback.onLoadFailed(e, model, target, isFirstResource); 96 | } 97 | 98 | @Override public boolean onResourceReady(TranscodeType resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { 99 | boolean callbackResult = this.callback != null && this.callback.onResourceReady(resource, model, target, dataSource, isFirstResource); 100 | 101 | Bitmap b = null; 102 | if (resource instanceof BitmapDrawable) { 103 | b = ((BitmapDrawable) resource).getBitmap(); 104 | } else if (resource instanceof GifDrawable) { 105 | b = ((GifDrawable) resource).getFirstFrame(); 106 | } else if (target instanceof BitmapHolder) { 107 | b = ((BitmapHolder) target).getBitmap(); 108 | } 109 | 110 | if (b != null) { 111 | start(b); 112 | } 113 | 114 | return callbackResult; 115 | } 116 | 117 | public interface BitmapHolder { 118 | @Nullable 119 | Bitmap getBitmap(); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/cache/core/LruDiskCache.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.cache.core; 3 | 4 | 5 | import com.jakewharton.disklrucache.DiskLruCache; 6 | import com.wls.wnlibrary.utils.net.cache.converter.IDiskConverter; 7 | import com.wls.wnlibrary.utils.net.utils.Utils; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.lang.reflect.Type; 14 | 15 | 16 | /** 17 | *

描述:磁盘缓存实现类

18 | * 1.为了更好的扩展功能,统一使用BasicCache
19 | * 2.将来做内存管理也可以继承BasicCache来统一处理
20 | */ 21 | public class LruDiskCache extends BaseCache { 22 | private IDiskConverter mDiskConverter; 23 | private DiskLruCache mDiskLruCache; 24 | 25 | 26 | public LruDiskCache(IDiskConverter diskConverter, File diskDir, int appVersion, long diskMaxSize) { 27 | this.mDiskConverter = Utils.checkNotNull(diskConverter, "diskConverter ==null"); 28 | try { 29 | mDiskLruCache = DiskLruCache.open(diskDir, appVersion, 1, diskMaxSize); 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | @Override 36 | protected T doLoad(Type type, String key) { 37 | if (mDiskLruCache == null) { 38 | return null; 39 | } 40 | try { 41 | DiskLruCache.Editor edit = mDiskLruCache.edit(key); 42 | if (edit == null) { 43 | return null; 44 | } 45 | 46 | InputStream source = edit.newInputStream(0); 47 | T value; 48 | if (source != null) { 49 | value = mDiskConverter.load(source,type); 50 | Utils.close(source); 51 | edit.commit(); 52 | return value; 53 | } 54 | edit.abort(); 55 | } catch (IOException e) { 56 | e.printStackTrace(); 57 | } 58 | return null; 59 | } 60 | 61 | @Override 62 | protected boolean doSave(String key, T value) { 63 | if (mDiskLruCache == null) { 64 | return false; 65 | } 66 | try { 67 | DiskLruCache.Editor edit = mDiskLruCache.edit(key); 68 | if (edit == null) { 69 | return false; 70 | } 71 | OutputStream sink = edit.newOutputStream(0); 72 | if (sink != null) { 73 | boolean result = mDiskConverter.writer(sink, value); 74 | Utils.close(sink); 75 | edit.commit(); 76 | return result; 77 | } 78 | edit.abort(); 79 | } catch (IOException e) { 80 | e.printStackTrace(); 81 | } 82 | return false; 83 | } 84 | 85 | @Override 86 | protected boolean doContainsKey(String key) { 87 | if (mDiskLruCache == null) { 88 | return false; 89 | } 90 | try { 91 | return mDiskLruCache.get(key) != null; 92 | } catch (IOException e) { 93 | e.printStackTrace(); 94 | } 95 | return false; 96 | } 97 | 98 | @Override 99 | protected boolean doRemove(String key) { 100 | if (mDiskLruCache == null) { 101 | return false; 102 | } 103 | try { 104 | return mDiskLruCache.remove(key); 105 | } catch (IOException e) { 106 | e.printStackTrace(); 107 | } 108 | return false; 109 | } 110 | 111 | 112 | @Override 113 | protected boolean doClear() { 114 | boolean statu = false; 115 | try { 116 | mDiskLruCache.delete(); 117 | statu = true; 118 | } catch (IOException e) { 119 | e.printStackTrace(); 120 | } 121 | return statu; 122 | } 123 | 124 | @Override 125 | protected boolean isExpiry(String key, long existTime) { 126 | if (mDiskLruCache == null) { 127 | return false; 128 | } 129 | if (existTime > -1) {//-1表示永久性存储 不用进行过期校验 130 | //为什么这么写,请了解DiskLruCache,看它的源码 131 | File file = new File(mDiskLruCache.getDirectory(), key + "." + 0); 132 | if (isCacheDataFailure(file, existTime)) {//没有获取到缓存,或者缓存已经过期! 133 | return true; 134 | } 135 | } 136 | return false; 137 | } 138 | 139 | /** 140 | * 判断缓存是否已经失效 141 | */ 142 | private boolean isCacheDataFailure(File dataFile, long time) { 143 | if (!dataFile.exists()) { 144 | return false; 145 | } 146 | long existTime = System.currentTimeMillis() - dataFile.lastModified(); 147 | return existTime > time*1000; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/PutRequest.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.wls.wnlibrary.utils.net.request; 4 | 5 | import com.google.gson.reflect.TypeToken; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.callback.CallBackProxy; 9 | import com.wls.wnlibrary.utils.net.callback.CallClazzProxy; 10 | import com.wls.wnlibrary.utils.net.func.ApiResultFunc; 11 | import com.wls.wnlibrary.utils.net.func.CacheResultFunc; 12 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 13 | import com.wls.wnlibrary.utils.net.model.ApiResult; 14 | import com.wls.wnlibrary.utils.net.subsciber.CallBackSubsciber; 15 | import com.wls.wnlibrary.utils.net.utils.RxUtil; 16 | 17 | import java.lang.reflect.Type; 18 | 19 | import io.reactivex.Observable; 20 | import io.reactivex.ObservableSource; 21 | import io.reactivex.ObservableTransformer; 22 | import io.reactivex.annotations.NonNull; 23 | import io.reactivex.disposables.Disposable; 24 | import okhttp3.RequestBody; 25 | import okhttp3.ResponseBody; 26 | 27 | /** 28 | *

描述:Put请求

29 | */ 30 | public class PutRequest extends BaseBodyRequest { 31 | public PutRequest(String url) { 32 | super(url); 33 | } 34 | 35 | public Observable execute(Class clazz) { 36 | return execute(new CallClazzProxy, T>(clazz) { 37 | }); 38 | } 39 | 40 | public Observable execute(Type type) { 41 | return execute(new CallClazzProxy, T>(type) { 42 | }); 43 | } 44 | 45 | @SuppressWarnings(value={"unchecked", "deprecation"}) 46 | public Observable execute(CallClazzProxy, T> proxy) { 47 | return build().generateRequest() 48 | .map(new ApiResultFunc(proxy.getType())) 49 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 50 | .compose(rxCache.transformer(cacheMode, proxy.getCallType())) 51 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)) 52 | .compose(new ObservableTransformer() { 53 | @Override 54 | public ObservableSource apply(@NonNull Observable upstream) { 55 | return upstream.map(new CacheResultFunc()); 56 | } 57 | }); 58 | } 59 | 60 | public Disposable execute(CallBack callBack) { 61 | return execute(new CallBackProxy, T>(callBack) { 62 | }); 63 | } 64 | 65 | @SuppressWarnings("unchecked") 66 | public Disposable execute(CallBackProxy, T> proxy) { 67 | Observable> observable = build().toObservable(generateRequest(), proxy); 68 | if (CacheResult.class != proxy.getCallBack().getRawType()) { 69 | return observable.compose(new ObservableTransformer, T>() { 70 | @Override 71 | public ObservableSource apply(@NonNull Observable> upstream) { 72 | return upstream.map(new CacheResultFunc()); 73 | } 74 | }).subscribeWith(new CallBackSubsciber(context, proxy.getCallBack())); 75 | } else { 76 | return observable.subscribeWith(new CallBackSubsciber>(context, proxy.getCallBack())); 77 | } 78 | } 79 | 80 | @SuppressWarnings("unchecked") 81 | private Observable> toObservable(Observable observable, CallBackProxy, T> proxy) { 82 | return observable.map(new ApiResultFunc(proxy != null ? proxy.getType() : new TypeToken() { 83 | }.getType())) 84 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 85 | .compose(rxCache.transformer(cacheMode, proxy.getCallBack().getType())) 86 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 87 | } 88 | 89 | @Override 90 | protected Observable generateRequest() { 91 | if (this.requestBody != null) { //自定义的请求体 92 | return apiManager.putBody(url, this.requestBody); 93 | } else if (this.json != null) {//Json 94 | RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), this.json); 95 | return apiManager.putJson(url, body); 96 | } else if (this.object != null) {//自定义的请求object 97 | return apiManager.putBody(url, object); 98 | } else if (this.string != null) {//文本内容 99 | RequestBody body = RequestBody.create(mediaType, this.string); 100 | return apiManager.putBody(url, body); 101 | } else { 102 | return apiManager.put(url, params.urlParamsMap); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.wls.wnlibrary.utils.base; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.View; 8 | 9 | public abstract class BaseFragment extends Fragment { 10 | 11 | private static final String TAG = BaseFragment.class.getSimpleName(); 12 | 13 | private boolean isFragmentVisible; 14 | private boolean isReuseView; 15 | private boolean isFirstVisible; 16 | private View rootView; 17 | 18 | 19 | //setUserVisibleHint()在Fragment创建时会先被调用一次,传入isVisibleToUser = false 20 | //如果当前Fragment可见,那么setUserVisibleHint()会再次被调用一次,传入isVisibleToUser = true 21 | //如果Fragment从可见->不可见,那么setUserVisibleHint()也会被调用,传入isVisibleToUser = false 22 | //总结:setUserVisibleHint()除了Fragment的可见状态发生变化时会被回调外,在new Fragment()时也会被回调 23 | //如果我们需要在 Fragment 可见与不可见时干点事,用这个的话就会有多余的回调了,那么就需要重新封装一个 24 | @Override 25 | public void setUserVisibleHint(boolean isVisibleToUser) { 26 | super.setUserVisibleHint(isVisibleToUser); 27 | //setUserVisibleHint()有可能在fragment的生命周期外被调用 28 | if (rootView == null) { 29 | return; 30 | } 31 | if (isFirstVisible && isVisibleToUser) { 32 | onFragmentFirstVisible(); 33 | isFirstVisible = false; 34 | } 35 | if (isVisibleToUser) { 36 | onFragmentVisibleChange(true); 37 | isFragmentVisible = true; 38 | return; 39 | } 40 | if (isFragmentVisible) { 41 | isFragmentVisible = false; 42 | onFragmentVisibleChange(false); 43 | } 44 | } 45 | 46 | @Override 47 | public void onCreate(@Nullable Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | initVariable(); 50 | } 51 | 52 | @Override 53 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 54 | //如果setUserVisibleHint()在rootView创建前调用时,那么 55 | //就等到rootView创建完后才回调onFragmentVisibleChange(true) 56 | //保证onFragmentVisibleChange()的回调发生在rootView创建完成之后,以便支持ui操作 57 | if (rootView == null) { 58 | rootView = view; 59 | if (getUserVisibleHint()) { 60 | if (isFirstVisible) { 61 | onFragmentFirstVisible(); 62 | isFirstVisible = false; 63 | } 64 | onFragmentVisibleChange(true); 65 | isFragmentVisible = true; 66 | } 67 | } 68 | super.onViewCreated(isReuseView ? rootView : view, savedInstanceState); 69 | } 70 | 71 | @Override 72 | public void onDestroyView() { 73 | super.onDestroyView(); 74 | } 75 | 76 | @Override 77 | public void onDestroy() { 78 | super.onDestroy(); 79 | initVariable(); 80 | } 81 | 82 | private void initVariable() { 83 | isFirstVisible = true; 84 | isFragmentVisible = false; 85 | rootView = null; 86 | isReuseView = true; 87 | } 88 | 89 | /** 90 | * 设置是否使用 view 的复用,默认开启 91 | * view 的复用是指,ViewPager 在销毁和重建 Fragment 时会不断调用 onCreateView() -> onDestroyView() 92 | * 之间的生命函数,这样可能会出现重复创建 view 的情况,导致界面上显示多个相同的 Fragment 93 | * view 的复用其实就是指保存第一次创建的 view,后面再 onCreateView() 时直接返回第一次创建的 view 94 | * 95 | * @param isReuse 96 | */ 97 | protected void reuseView(boolean isReuse) { 98 | isReuseView = isReuse; 99 | } 100 | 101 | /** 102 | * 去除setUserVisibleHint()多余的回调场景,保证只有当fragment可见状态发生变化时才回调 103 | * 回调时机在view创建完后,所以支持ui操作,解决在setUserVisibleHint()里进行ui操作有可能报null异常的问题 104 | *

105 | * 可在该回调方法里进行一些ui显示与隐藏,比如加载框的显示和隐藏 106 | * 107 | * @param isVisible true 不可见 -> 可见 108 | * false 可见 -> 不可见 109 | */ 110 | protected void onFragmentVisibleChange(boolean isVisible) { 111 | 112 | } 113 | 114 | /** 115 | * 在fragment首次可见时回调,可在这里进行加载数据,保证只在第一次打开Fragment时才会加载数据, 116 | * 这样就可以防止每次进入都重复加载数据 117 | * 该方法会在 onFragmentVisibleChange() 之前调用,所以第一次打开时,可以用一个全局变量表示数据下载状态, 118 | * 然后在该方法内将状态设置为下载状态,接着去执行下载的任务 119 | * 最后在 onFragmentVisibleChange() 里根据数据下载状态来控制下载进度ui控件的显示与隐藏 120 | */ 121 | protected void onFragmentFirstVisible() { 122 | 123 | } 124 | 125 | protected boolean isFragmentVisible() { 126 | return isFragmentVisible; 127 | } 128 | 129 | /** 130 | * 检查运行时权限 131 | * 132 | * @param permissions 所检查的权限数组 133 | * @param runtimePermissionListener 运行时权限监听器 134 | */ 135 | public void checkRuntimePermission(String[] permissions, BaseActivity.RuntimePermissionListener runtimePermissionListener) { 136 | Activity activity = getActivity(); 137 | if (activity instanceof BaseActivity) { 138 | ((BaseActivity) activity).checkRuntimePermission(permissions, runtimePermissionListener); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /wnlibrary/src/main/java/com/wls/wnlibrary/utils/net/request/CustomRequest.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wls.wnlibrary.utils.net.request; 3 | 4 | 5 | import com.google.gson.reflect.TypeToken; 6 | import com.wls.wnlibrary.utils.net.cache.model.CacheResult; 7 | import com.wls.wnlibrary.utils.net.callback.CallBack; 8 | import com.wls.wnlibrary.utils.net.callback.CallBackProxy; 9 | import com.wls.wnlibrary.utils.net.func.ApiResultFunc; 10 | import com.wls.wnlibrary.utils.net.func.CacheResultFunc; 11 | import com.wls.wnlibrary.utils.net.func.HandleFuc; 12 | import com.wls.wnlibrary.utils.net.func.RetryExceptionFunc; 13 | import com.wls.wnlibrary.utils.net.model.ApiResult; 14 | import com.wls.wnlibrary.utils.net.subsciber.CallBackSubsciber; 15 | import com.wls.wnlibrary.utils.net.transformer.HandleErrTransformer; 16 | import com.wls.wnlibrary.utils.net.utils.RxUtil; 17 | import com.wls.wnlibrary.utils.net.utils.Utils; 18 | 19 | 20 | import io.reactivex.Observable; 21 | import io.reactivex.ObservableSource; 22 | import io.reactivex.ObservableTransformer; 23 | import io.reactivex.Observer; 24 | import io.reactivex.annotations.NonNull; 25 | import io.reactivex.disposables.Disposable; 26 | import okhttp3.ResponseBody; 27 | 28 | /** 29 | *

描述:自定义请求,例如你有自己的ApiService

30 | */ 31 | @SuppressWarnings(value={"unchecked", "deprecation"}) 32 | public class CustomRequest extends BaseRequest { 33 | public CustomRequest() { 34 | super(""); 35 | } 36 | 37 | @Override 38 | public CustomRequest build() { 39 | return super.build(); 40 | } 41 | 42 | /** 43 | * 创建api服务 可以支持自定义的api,默认使用BaseApiService,上层不用关心 44 | * 45 | * @param service 自定义的apiservice class 46 | */ 47 | public T create(final Class service) { 48 | checkvalidate(); 49 | return retrofit.create(service); 50 | } 51 | 52 | private void checkvalidate() { 53 | Utils.checkNotNull(retrofit, "请先在调用build()才能使用"); 54 | } 55 | 56 | /** 57 | * 调用call返回一个Observable 58 | * 举例:如果你给的是一个Observable> 那么返回的是一个ApiResult 59 | */ 60 | public Observable call(Observable observable) { 61 | checkvalidate(); 62 | return observable.compose(RxUtil.io_main()) 63 | .compose(new HandleErrTransformer()) 64 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 65 | } 66 | 67 | public void call(Observable observable, CallBack callBack) { 68 | call(observable, new CallBackSubsciber(context, callBack)); 69 | } 70 | 71 | public void call(Observable observable, Observer subscriber) { 72 | observable.compose(RxUtil.io_main()) 73 | .subscribe(subscriber); 74 | } 75 | 76 | 77 | /** 78 | * 调用call返回一个Observable,针对ApiResult的业务 79 | * 举例:如果你给的是一个Observable> 那么返回的是AuthModel 80 | */ 81 | public Observable apiCall(Observable> observable) { 82 | checkvalidate(); 83 | return observable 84 | .map(new HandleFuc()) 85 | .compose(RxUtil.io_main()) 86 | .compose(new HandleErrTransformer()) 87 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 88 | } 89 | 90 | public Disposable apiCall(Observable observable, CallBack callBack) { 91 | return call(observable, new CallBackProxy, T>(callBack) { 92 | }); 93 | } 94 | 95 | public Disposable call(Observable observable, CallBackProxy, T> proxy) { 96 | Observable> cacheobservable = build().toObservable(observable, proxy); 97 | if (CacheResult.class != proxy.getCallBack().getRawType()) { 98 | return cacheobservable.compose(new ObservableTransformer, T>() { 99 | @Override 100 | public ObservableSource apply(@NonNull Observable> upstream) { 101 | return upstream.map(new CacheResultFunc()); 102 | } 103 | }).subscribeWith(new CallBackSubsciber(context, proxy.getCallBack())); 104 | } else { 105 | return cacheobservable.subscribeWith(new CallBackSubsciber>(context, proxy.getCallBack())); 106 | } 107 | } 108 | 109 | @SuppressWarnings(value={"unchecked", "deprecation"}) 110 | private Observable> toObservable(Observable observable, CallBackProxy, T> proxy) { 111 | return observable.map(new ApiResultFunc(proxy != null ? proxy.getType() : new TypeToken() { 112 | }.getType())) 113 | .compose(isSyncRequest ? RxUtil._main() : RxUtil._io_main()) 114 | .compose(rxCache.transformer(cacheMode, proxy.getCallBack().getType())) 115 | .retryWhen(new RetryExceptionFunc(retryCount, retryDelay, retryIncreaseDelay)); 116 | } 117 | 118 | @Override 119 | protected Observable generateRequest() { 120 | return null; 121 | } 122 | } 123 | --------------------------------------------------------------------------------