├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── themes.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 │ │ │ ├── values-night │ │ │ │ └── themes.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── allens │ │ │ │ └── tea │ │ │ │ ├── MainViewModel.kt │ │ │ │ └── RegisterData.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── allens │ │ │ └── tea │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── allens │ │ └── tea │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── moya ├── .gitignore ├── consumer-rules.pro ├── src │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── allens │ │ │ │ └── moya │ │ │ │ ├── impl │ │ │ │ ├── OnLogInterceptor.kt │ │ │ │ ├── OnDownLoadInterceptor.kt │ │ │ │ ├── OnCookieInterceptor.kt │ │ │ │ └── OnDownLoadListener.kt │ │ │ │ ├── request │ │ │ │ ├── BasicDownLoadRequest.kt │ │ │ │ ├── DownLoadRequest.kt │ │ │ │ ├── ProgressRequestBody.kt │ │ │ │ └── Request.kt │ │ │ │ ├── enums │ │ │ │ ├── NetWorkCacheType.kt │ │ │ │ ├── NoNetWorkCacheType.kt │ │ │ │ ├── CacheType.kt │ │ │ │ ├── LoggerLevel.kt │ │ │ │ └── TimeUnitEnum.kt │ │ │ │ ├── dslMarker │ │ │ │ └── Marker.kt │ │ │ │ ├── tools │ │ │ │ ├── MoyaLogTool.kt │ │ │ │ ├── UrlTool.kt │ │ │ │ ├── PrefTools.kt │ │ │ │ └── FileTool.kt │ │ │ │ ├── config │ │ │ │ ├── NetWorkTimeOut.kt │ │ │ │ ├── LoggerConfig.kt │ │ │ │ ├── DefaultConfig.kt │ │ │ │ ├── NetWorkCache.kt │ │ │ │ └── MoyaConfig.kt │ │ │ │ ├── result │ │ │ │ ├── UpLoadResult.kt │ │ │ │ ├── Disposable.kt │ │ │ │ ├── DownLoadResult.kt │ │ │ │ └── HttpResult.kt │ │ │ │ ├── delegate │ │ │ │ └── LambdaDelegate.kt │ │ │ │ ├── interceptor │ │ │ │ ├── HeardInterceptor.kt │ │ │ │ ├── LogInterceptor.kt │ │ │ │ ├── CacheNetworkInterceptor.kt │ │ │ │ ├── ParameterInterceptor.kt │ │ │ │ ├── ReceivedCookieInterceptor.kt │ │ │ │ ├── DynamicBaseUrlInterceptor.kt │ │ │ │ ├── DynamicTimeoutInterceptor.kt │ │ │ │ └── CacheInterceptor.kt │ │ │ │ ├── message │ │ │ │ └── MoyaMessage.kt │ │ │ │ ├── MoyaDSL.kt │ │ │ │ ├── livedata │ │ │ │ └── DownLoadStatusLiveData.kt │ │ │ │ └── manager │ │ │ │ └── HttpManager.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── allens │ │ │ └── moya │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── allens │ │ └── moya │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── moya-coroutines ├── .gitignore ├── consumer-rules.pro ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ └── kotlin │ │ │ └── com │ │ │ └── allens │ │ │ └── moya_coroutines │ │ │ ├── request │ │ │ ├── CoroutinesDownLoadRequest.kt │ │ │ ├── CoroutinesDisposable.kt │ │ │ ├── PutRequest.kt │ │ │ ├── DeleteRequest.kt │ │ │ ├── GetRequest.kt │ │ │ ├── UploadRequest.kt │ │ │ ├── DownLoadRequest.kt │ │ │ ├── PostRequest.kt │ │ │ └── RequestBasis.kt │ │ │ ├── manager │ │ │ └── CoroutinesDownLoadManager.kt │ │ │ └── impl │ │ │ └── ApiService.kt │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── allens │ │ │ └── moya_coroutines │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── allens │ │ └── moya_coroutines │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── versionPlugin ├── build │ ├── tmp │ │ └── jar │ │ │ └── MANIFEST.MF │ ├── kotlin │ │ ├── compileKotlin │ │ │ ├── caches-jvm │ │ │ │ ├── lookups │ │ │ │ │ ├── counters.tab │ │ │ │ │ ├── lookups.tab.len │ │ │ │ │ ├── id-to-file.tab.len │ │ │ │ │ ├── file-to-id.tab.keystream.len │ │ │ │ │ ├── id-to-file.tab.keystream.len │ │ │ │ │ ├── lookups.tab │ │ │ │ │ ├── file-to-id.tab │ │ │ │ │ ├── id-to-file.tab │ │ │ │ │ ├── lookups.tab_i │ │ │ │ │ ├── file-to-id.tab_i │ │ │ │ │ ├── id-to-file.tab_i │ │ │ │ │ ├── file-to-id.tab.len │ │ │ │ │ ├── lookups.tab_i.len │ │ │ │ │ ├── file-to-id.tab_i.len │ │ │ │ │ ├── id-to-file.tab_i.len │ │ │ │ │ ├── lookups.tab.keystream │ │ │ │ │ ├── lookups.tab.keystream.len │ │ │ │ │ ├── file-to-id.tab.values.at │ │ │ │ │ ├── id-to-file.tab.values.at │ │ │ │ │ ├── lookups.tab.values.at │ │ │ │ │ ├── file-to-id.tab.keystream │ │ │ │ │ └── id-to-file.tab.keystream │ │ │ │ ├── jvm │ │ │ │ │ └── kotlin │ │ │ │ │ │ ├── constants.tab.len │ │ │ │ │ │ ├── proto.tab.len │ │ │ │ │ │ ├── class-attributes.tab.len │ │ │ │ │ │ ├── subtypes.tab.keystream.len │ │ │ │ │ │ ├── class-fq-name-to-source.tab.len │ │ │ │ │ │ ├── internal-name-to-source.tab.len │ │ │ │ │ │ ├── supertypes.tab.keystream.len │ │ │ │ │ │ ├── source-to-classes.tab.keystream.len │ │ │ │ │ │ ├── proto.tab │ │ │ │ │ │ ├── proto.tab_i │ │ │ │ │ │ ├── subtypes.tab.values.at │ │ │ │ │ │ ├── constants.tab │ │ │ │ │ │ ├── subtypes.tab │ │ │ │ │ │ ├── supertypes.tab.values.at │ │ │ │ │ │ ├── constants.tab_i │ │ │ │ │ │ ├── proto.tab_i.len │ │ │ │ │ │ ├── subtypes.tab.len │ │ │ │ │ │ ├── subtypes.tab_i │ │ │ │ │ │ ├── supertypes.tab │ │ │ │ │ │ ├── supertypes.tab_i │ │ │ │ │ │ ├── subtypes.tab_i.len │ │ │ │ │ │ ├── supertypes.tab.len │ │ │ │ │ │ ├── class-attributes.tab │ │ │ │ │ │ ├── constants.tab_i.len │ │ │ │ │ │ ├── proto.tab.values.at │ │ │ │ │ │ ├── source-to-classes.tab │ │ │ │ │ │ ├── supertypes.tab_i.len │ │ │ │ │ │ ├── class-attributes.tab_i │ │ │ │ │ │ ├── constants.tab.values.at │ │ │ │ │ │ ├── proto.tab.keystream.len │ │ │ │ │ │ ├── source-to-classes.tab_i │ │ │ │ │ │ ├── class-attributes.tab_i.len │ │ │ │ │ │ ├── source-to-classes.tab.len │ │ │ │ │ │ ├── class-fq-name-to-source.tab │ │ │ │ │ │ ├── constants.tab.keystream.len │ │ │ │ │ │ ├── internal-name-to-source.tab │ │ │ │ │ │ ├── source-to-classes.tab_i.len │ │ │ │ │ │ ├── class-fq-name-to-source.tab_i │ │ │ │ │ │ ├── internal-name-to-source.tab_i │ │ │ │ │ │ ├── source-to-classes.tab.values.at │ │ │ │ │ │ ├── class-fq-name-to-source.tab_i.len │ │ │ │ │ │ ├── internal-name-to-source.tab_i.len │ │ │ │ │ │ ├── class-attributes.tab.keystream.len │ │ │ │ │ │ ├── class-fq-name-to-source.tab.keystream.len │ │ │ │ │ │ ├── internal-name-to-source.tab.keystream.len │ │ │ │ │ │ ├── class-attributes.tab.values.at │ │ │ │ │ │ ├── proto.tab.keystream │ │ │ │ │ │ ├── constants.tab.keystream │ │ │ │ │ │ ├── subtypes.tab.keystream │ │ │ │ │ │ ├── supertypes.tab.keystream │ │ │ │ │ │ ├── class-attributes.tab.keystream │ │ │ │ │ │ ├── source-to-classes.tab.keystream │ │ │ │ │ │ ├── class-fq-name-to-source.tab.keystream │ │ │ │ │ │ └── internal-name-to-source.tab.keystream │ │ │ │ └── inputs │ │ │ │ │ ├── source-to-output.tab.keystream.len │ │ │ │ │ ├── source-to-output.tab │ │ │ │ │ ├── source-to-output.tab_i │ │ │ │ │ ├── source-to-output.tab.len │ │ │ │ │ ├── source-to-output.tab_i.len │ │ │ │ │ ├── source-to-output.tab.values.at │ │ │ │ │ └── source-to-output.tab.keystream │ │ │ ├── last-build.bin │ │ │ └── build-history.bin │ │ └── versionPluginjar-classes.txt │ ├── classes │ │ └── kotlin │ │ │ └── main │ │ │ ├── META-INF │ │ │ └── versionPlugin.kotlin_module │ │ │ └── com │ │ │ └── allens │ │ │ └── tea │ │ │ ├── Deps.class │ │ │ ├── Libs.class │ │ │ ├── BuildConfig.class │ │ │ ├── Libs$AndroidX.class │ │ │ ├── Libs$Custom.class │ │ │ ├── Libs$Google.class │ │ │ ├── Libs$Kotlin.class │ │ │ ├── Libs$Squareup.class │ │ │ ├── Libs$Tencent.class │ │ │ ├── Libs$Lifecycle.class │ │ │ ├── Libs$AndroidX$Test.class │ │ │ ├── Libs$AndroidX$Test$Ext.class │ │ │ └── Libs$Squareup$OkHttp3.class │ ├── pluginDescriptors │ │ └── com.allens.plugin.properties │ ├── resources │ │ └── main │ │ │ └── META-INF │ │ │ └── gradle-plugins │ │ │ └── com.allens.plugin.properties │ └── libs │ │ └── versionPlugin.jar ├── src │ └── main │ │ └── java │ │ └── com │ │ └── allens │ │ └── tea │ │ ├── Deps.kt │ │ └── Dependencies.kt └── build.gradle ├── .idea ├── .gitignore ├── compiler.xml ├── vcs.xml ├── runConfigurations.xml ├── misc.xml ├── gradle.xml └── jarRepositories.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── settings.gradle ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── gradlew └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /moya/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /moya/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /moya-coroutines/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /moya-coroutines/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /versionPlugin/build/tmp/jar/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/counters.tab: -------------------------------------------------------------------------------- 1 | 19 2 | 17 -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.len: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.len: -------------------------------------------------------------------------------- 1 | ( -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.len: -------------------------------------------------------------------------------- 1 | 8 -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.len: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.len: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.keystream.len: -------------------------------------------------------------------------------- 1 | n -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.keystream.len: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/META-INF/versionPlugin.kotlin_module: -------------------------------------------------------------------------------- 1 | "* -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.keystream.len: -------------------------------------------------------------------------------- 1 | n -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | tea 3 | -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len: -------------------------------------------------------------------------------- 1 | n -------------------------------------------------------------------------------- /versionPlugin/build/pluginDescriptors/com.allens.plugin.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.allens.tea.Deps 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /versionPlugin/build/resources/main/META-INF/gradle-plugins/com.allens.plugin.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.allens.tea.Deps 2 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /versionPlugin/build/libs/versionPlugin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/libs/versionPlugin.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "tea" 2 | include ':app' 3 | includeBuild 'versionPlugin' 4 | include ':moya' 5 | include ':moya-coroutines' 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/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/JiangHaiYang01/Moya/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/JiangHaiYang01/Moya/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/JiangHaiYang01/Moya/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/JiangHaiYang01/Moya/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/java/com/allens/tea/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | class MainViewModel : ViewModel() { 6 | } -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/last-build.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/last-build.bin -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/build-history.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/build-history.bin -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/impl/OnLogInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.impl 2 | 3 | interface OnLogInterceptor { 4 | fun onLogInterceptorInfo(message: String) 5 | } -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Deps.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Deps.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs.class -------------------------------------------------------------------------------- /app/src/main/java/com/allens/tea/RegisterData.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 2 | 3 | data class RegisterData( 4 | val `data`: Any, 5 | val errorCode: Int, 6 | val errorMsg: String 7 | ) -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/BuildConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/BuildConfig.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Custom.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Custom.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Google.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Google.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Kotlin.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Kotlin.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Tencent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Tencent.class -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStoragecom.allens.tea.Depscom.allens.tea.Depscom.allens.tea.Deps -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Lifecycle.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Lifecycle.class -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStorageorg.gradle.api.Pluginorg.gradle.api.Pluginorg.gradle.api.Plugin -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test.class -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream -------------------------------------------------------------------------------- /moya-coroutines/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test$Ext.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test$Ext.class -------------------------------------------------------------------------------- /versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup$OkHttp3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup$OkHttp3.class -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.values.at: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.values.at -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.values.at: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.values.at -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.values.at: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.values.at -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStorage  2 |     -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/request/BasicDownLoadRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.request 2 | 3 | import com.allens.moya.manager.HttpManager 4 | 5 | open class BasicDownLoadRequest : DownLoadRequest() { 6 | lateinit var manager: HttpManager 7 | } -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiangHaiYang01/Moya/HEAD/versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len -------------------------------------------------------------------------------- /versionPlugin/src/main/java/com/allens/tea/Deps.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 2 | import org.gradle.api.Plugin 3 | import org.gradle.api.Project 4 | 5 | class Deps : Plugin { 6 | override fun apply(project: Project) { 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /moya/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/enums/NetWorkCacheType.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.enums 2 | 3 | enum class NetWorkCacheType { 4 | // 不加入缓存的逻辑 5 | NONE, 6 | 7 | // 有网络时候 实时加载 8 | NOCACHE, 9 | 10 | // 特定时间之后请求数据;(比如:特定时间为20s) 11 | CACHE_TIME, 12 | } 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed May 19 23:05:40 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/impl/OnDownLoadInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.impl 2 | 3 | import com.allens.moya.request.BasicDownLoadRequest 4 | 5 | 6 | interface OnDownLoadInterceptor { 7 | fun onIntercept(request: BasicDownLoadRequest,function:(Throwable)->Unit): Boolean 8 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/dslMarker/Marker.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.dslMarker 2 | 3 | /*** 4 | * 控制作用域范围 5 | */ 6 | 7 | 8 | @DslMarker 9 | annotation class CacheTagMarker 10 | 11 | @DslMarker 12 | annotation class TimeTagMarker 13 | 14 | @DslMarker 15 | annotation class LoggerMarker -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/enums/NoNetWorkCacheType.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.enums 2 | 3 | enum class NoNetWorkCacheType { 4 | // 不加入缓存的逻辑 5 | NONE, 6 | 7 | // 无限时请求有网请求好的数据; 8 | NO_TIMEOUT, 9 | 10 | // 特定时间之前请求有网请求好的数据;((比如:特定时间为20s)) 11 | HAS_TIMEOUT, 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/tools/MoyaLogTool.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.tools 2 | 3 | import android.util.Log 4 | import com.allens.moya.Moya 5 | 6 | 7 | object MoyaLogTool { 8 | 9 | fun i(info: String) { 10 | if (Moya.debug) { 11 | Log.i("moya-->", info) 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/CoroutinesDownLoadRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.request.BasicDownLoadRequest 4 | import kotlinx.coroutines.CoroutineScope 5 | 6 | class CoroutinesDownLoadRequest : BasicDownLoadRequest() { 7 | lateinit var coroutines: CoroutineScope 8 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/config/NetWorkTimeOut.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.config 2 | 3 | import com.allens.moya.dslMarker.TimeTagMarker 4 | 5 | @TimeTagMarker 6 | data class NetWorkTimeOut( 7 | var connect: Long = DefaultConfig.DEFAULT_TIME_OUT, 8 | var write: Long = DefaultConfig.DEFAULT_TIME_OUT, 9 | var read: Long = DefaultConfig.DEFAULT_TIME_OUT, 10 | ) 11 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/result/UpLoadResult.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.result 2 | 3 | 4 | class UpLoadBuilder : HttpBuilder() { 5 | var onProgress: (progress: Int, current: Long, length: Long) -> Unit = { _, _, _ -> } 6 | } 7 | 8 | 9 | data class UpLoadData( 10 | var disposable: T? = null, 11 | var builder: UpLoadBuilder 12 | ) -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/test/java/com/allens/tea/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 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 | } -------------------------------------------------------------------------------- /moya/src/test/java/com/allens/moya/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya 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 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/config/LoggerConfig.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.config 2 | 3 | import com.allens.moya.dslMarker.LoggerMarker 4 | import com.allens.moya.enums.LoggerLevel 5 | import com.allens.moya.impl.OnLogInterceptor 6 | 7 | 8 | @LoggerMarker 9 | data class LoggerConfig( 10 | var level: LoggerLevel = DefaultConfig.DEFAULT_LEVEL, 11 | var debug: Boolean = DefaultConfig.DEFAULT_DEBUG, 12 | var interceptors: Set? = null 13 | 14 | ) 15 | -------------------------------------------------------------------------------- /moya-coroutines/src/test/java/com/allens/moya_coroutines/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines 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 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/impl/OnCookieInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.impl 2 | 3 | interface OnCookieInterceptor { 4 | 5 | /*** 6 | * 是否拦截所有方法的cookie 7 | */ 8 | fun isInterceptorAllRequest(): Boolean { 9 | return false 10 | } 11 | 12 | /** 13 | * 拦截哪一个方法 14 | * [url] 会将url 返回作为鉴权的条件。开发者自行做逻辑示例 15 | */ 16 | fun interceptorRequestWithUrl(url: String): Boolean 17 | 18 | /** 19 | * 拦截返回 cookie 20 | */ 21 | fun onCookies(cookie: HashSet) 22 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/enums/CacheType.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.enums 2 | 3 | enum class CacheType { 4 | //不加入缓存的逻辑 5 | NONE, 6 | 7 | //有网时:每次都请求实时数据; 无网时:无限时请求有网请求好的数据; 8 | HAS_NETWORK_NOCACHE_AND_NO_NETWORK_NO_TIME, 9 | 10 | //有网时:特定时间之后请求数据; 无网时:无限时请求有网请求好的数据; 11 | HAS_NETWORK_CACHE_TIME_AND_NO_NETWORK_NO_TIME, 12 | 13 | //有网时:每次都请求实时数据; 无网时:特定时间之前请求有网请求好的数据; 14 | HAS_NETWORK_NOCACHE_AND_NO_NETWORK_HAS_TIME, 15 | 16 | //有网时:特定时间之后请求数据; 无网时:特定时间之前请求有网请求好的数据; 17 | HAS_NETWORK_CACHE_TIME_AND_NO_NETWORK_HAS_TIME, 18 | } -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/CoroutinesDisposable.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.result.Disposable 4 | import com.allens.moya.tools.MoyaLogTool 5 | import kotlinx.coroutines.Job 6 | 7 | class CoroutinesDisposable(private val job: Job) : Disposable { 8 | override val isDisposed 9 | get() = !job.isActive 10 | 11 | override fun dispose() { 12 | MoyaLogTool.i("CoroutinesDisposable dispose isActive:$isDisposed") 13 | if (isDisposed) return 14 | job.cancel() 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStorage -------------------------------------------------------------------------------- /versionPlugin/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | // 因为使用的 Kotlin 需要需要添加 Kotlin 插件 7 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0" 8 | } 9 | } 10 | 11 | apply plugin: 'kotlin' 12 | apply plugin: 'java-gradle-plugin' 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | gradlePlugin { 19 | plugins { 20 | version { 21 | // 在 app 模块需要通过 id 引用这个插件 22 | id = 'com.allens.plugin' 23 | // 实现这个插件的类的路径 24 | implementationClass = 'com.allens.tea.Deps' 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/delegate/LambdaDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.delegate 2 | 3 | import kotlin.properties.ReadWriteProperty 4 | import kotlin.reflect.KProperty 5 | 6 | @Suppress("UNCHECKED_CAST") 7 | class LambdaDelegate(val data: T, private val block: (T, R) -> Unit) : 8 | ReadWriteProperty Unit> { 9 | override fun getValue(thisRef: Any, property: KProperty<*>): T.() -> Unit { 10 | return {} 11 | } 12 | 13 | override fun setValue(thisRef: Any, property: KProperty<*>, value: T.() -> Unit) { 14 | data.apply { 15 | value(this) 16 | block(this, thisRef as R) 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/tools/UrlTool.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.tools 2 | 3 | object UrlTool { 4 | 5 | // 拼接URL 6 | fun prepareParam(paramMap: Map): String { 7 | val sb = StringBuilder() 8 | return if (paramMap.isEmpty()) { 9 | "" 10 | } else { 11 | for (key in paramMap.keys) { 12 | val value = paramMap[key] 13 | if (sb.isEmpty()) { 14 | sb.append(key).append("=").append(value) 15 | } else { 16 | sb.append("&").append(key).append("=").append(value) 17 | } 18 | } 19 | sb.toString() 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/enums/LoggerLevel.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.enums 2 | 3 | import okhttp3.logging.HttpLoggingInterceptor 4 | 5 | /** 6 | * 日志等级 7 | */ 8 | enum class LoggerLevel { 9 | NONE, 10 | BASIC, 11 | HEADERS, 12 | BODY; 13 | 14 | companion object { 15 | fun conversion(level: LoggerLevel): HttpLoggingInterceptor.Level { 16 | return when (level) { 17 | BODY -> HttpLoggingInterceptor.Level.BODY 18 | NONE -> HttpLoggingInterceptor.Level.NONE 19 | BASIC -> HttpLoggingInterceptor.Level.BASIC 20 | HEADERS -> HttpLoggingInterceptor.Level.HEADERS 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/config/DefaultConfig.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.config 2 | 3 | import com.allens.moya.enums.LoggerLevel 4 | 5 | /** 6 | * 默认的配置参数 7 | */ 8 | internal class DefaultConfig { 9 | 10 | companion object { 11 | const val DEFAULT_CACHE_PATH = "cacheHttp" 12 | const val DEFAULT_BASE_URL = "" 13 | const val DEFAULT_CACHE_NETWORK_TIMEOUT = 20 14 | const val DEFAULT_NO_CACHE_NETWORK_TIMEOUT = 30 * 24 * 60 * 60 15 | const val DEFAULT_CACHE_SIZE = 10 * 1024 * 1024 16 | const val DEFAULT_TIME_OUT = 10L 17 | const val DEFAULT_RETRY = true 18 | const val DEFAULT_DEBUG = false 19 | val DEFAULT_LEVEL = LoggerLevel.BODY 20 | } 21 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/tools/PrefTools.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.tools 2 | 3 | 4 | import android.content.Context 5 | import com.allens.moya.request.DownLoadRequest 6 | import com.tencent.mmkv.MMKV 7 | 8 | 9 | object PrefTools { 10 | fun init(context: Context) { 11 | MMKV.initialize(context.applicationContext) 12 | } 13 | 14 | fun getLong(request: DownLoadRequest): Long { 15 | return MMKV.defaultMMKV()?.decodeLong(request.url, 0L) ?: 0L 16 | } 17 | 18 | fun putLong(request: DownLoadRequest, progress: Long) { 19 | MMKV.defaultMMKV()?.encode(request.url, progress) 20 | } 21 | 22 | fun remove(request: DownLoadRequest) { 23 | MMKV.defaultMMKV()?.remove(request.url) 24 | } 25 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/result/Disposable.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.result 2 | 3 | interface Disposable { 4 | val isDisposed: Boolean 5 | fun dispose() 6 | } 7 | 8 | 9 | class DownLoadBuilder { 10 | lateinit var onPrepare: (tag: String) -> Unit 11 | lateinit var onProgress: (tag: String, progress: Int) -> Unit 12 | lateinit var onUpdate: ( 13 | tag: String, 14 | progress: Int, 15 | read: Long, 16 | count: Long, 17 | done: Boolean 18 | ) -> Unit 19 | lateinit var onSuccess: (tag: String, path: String) -> Unit 20 | lateinit var onError: (tag: String, Throwable) -> Unit 21 | lateinit var onCancel: (tag: String) -> Unit 22 | lateinit var onPause: (tag: String) -> Unit 23 | 24 | } 25 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/result/DownLoadResult.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.result 2 | 3 | import com.allens.moya.livedata.DownLoadStatusLiveData 4 | 5 | sealed class DownLoadResult { 6 | 7 | object Prepare : DownLoadResult() 8 | object Cancel : DownLoadResult() 9 | object Pause : DownLoadResult() 10 | data class Success(val data: String) : DownLoadResult() 11 | data class Error(val throwable: Throwable) : DownLoadResult() 12 | data class Progress( 13 | val progress: Int, 14 | val read: Long, 15 | val count: Long, 16 | val done: Boolean 17 | ) : DownLoadResult() 18 | 19 | } 20 | 21 | data class DownLoadData( 22 | var liveData: DownLoadStatusLiveData? = null, 23 | var disposable: T? = null 24 | ) -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/HeardInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import com.allens.moya.tools.MoyaLogTool 4 | import okhttp3.Interceptor 5 | import okhttp3.Request 6 | 7 | /** 8 | * 为所有请求添加请求头 9 | */ 10 | object HeardInterceptor { 11 | fun register(map: Map): Interceptor { 12 | return Interceptor { chain: Interceptor.Chain -> 13 | val request = chain.request() 14 | val builder: Request.Builder = request.newBuilder() 15 | for ((key, value) in map.entries) { 16 | MoyaLogTool.i( "add heard [key]:$key [value]:$value ") 17 | builder.addHeader(key, value) 18 | } 19 | chain.proceed(builder.build()) 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/allens/tea/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.allens.tea", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /moya/src/androidTest/java/com/allens/moya/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.allens.moya.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /moya/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 -------------------------------------------------------------------------------- /moya-coroutines/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 -------------------------------------------------------------------------------- /moya-coroutines/src/androidTest/java/com/allens/moya_coroutines/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.allens.moya_coroutines.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/config/NetWorkCache.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.config 2 | 3 | import com.allens.moya.dslMarker.CacheTagMarker 4 | import com.allens.moya.enums.CacheType 5 | import com.allens.moya.enums.NetWorkCacheType 6 | import com.allens.moya.enums.NoNetWorkCacheType 7 | 8 | 9 | @CacheTagMarker 10 | data class NetWorkCache( 11 | 12 | // 缓存策略 默认不加入缓存的逻辑 13 | var type :CacheType = CacheType.NONE, 14 | 15 | // 有网时:特定时间之后请求数据;(比如:特定时间为20s) 默认20 16 | var networkTimeOut: Int = DefaultConfig.DEFAULT_CACHE_NETWORK_TIMEOUT, 17 | 18 | // 无网时:特定时间之前请求有网请求好的数据;((比如:特定时间为30天) 默认30 天 单位(秒) 19 | var noNetworkTimeOut: Int = DefaultConfig.DEFAULT_NO_CACHE_NETWORK_TIMEOUT, 20 | 21 | // 缓存大小 10M 22 | var size: Int = DefaultConfig.DEFAULT_CACHE_SIZE, 23 | 24 | // 缓存位置 25 | var path: String = DefaultConfig.DEFAULT_CACHE_PATH, 26 | ) -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/message/MoyaMessage.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.message 2 | 3 | import androidx.annotation.experimental.Experimental 4 | 5 | class MoyaMessage { 6 | 7 | companion object { 8 | private const val METHOD = "(\n" + 9 | " parameter: String,\n" + 10 | " crossinline init: HttpBuilder.() -> Unit\n" + 11 | ")" 12 | 13 | const val IMPORTS = "Request.Builder" 14 | const val Deprecated = "The use of lambda in this method is not elegant." 15 | private const val EXPRESSION = "It is recommended to use within the coroutine \n" 16 | const val GET = EXPRESSION + "doGet" + METHOD 17 | const val POST = EXPRESSION + "doPost" + METHOD 18 | const val DELETE = EXPRESSION + "doDelete" + METHOD 19 | const val BODY = EXPRESSION + "doBody" + METHOD 20 | const val PUT = EXPRESSION + "doPut" + METHOD 21 | const val doUpLoad = EXPRESSION + "doUpLoad" + METHOD 22 | 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/impl/OnDownLoadListener.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.impl 2 | 3 | 4 | interface OnDownLoadProgressListener { 5 | /** 6 | * 下载进度 7 | * 8 | * @param key 如果设置了tag 就是tag 如何没设置 就是 url 9 | * @param progress 进度 10 | * @param read 读取 11 | * @param count 总共长度 12 | * @param done 是否完成 13 | */ 14 | fun onUpdate( 15 | key: String, 16 | progress: Int, 17 | read: Long, 18 | count: Long, 19 | done: Boolean 20 | ){} 21 | } 22 | 23 | 24 | interface OnDownLoadListener : OnDownLoadProgressListener { 25 | 26 | 27 | /** 28 | * 等待下载 29 | * @param key String 30 | */ 31 | fun onDownLoadPrepare(key: String) 32 | 33 | // 进度 34 | fun onDownLoadProgress(key: String, progress: Int) 35 | 36 | // 下载失败 37 | fun onDownLoadError(key: String, throwable: Throwable) 38 | 39 | // 下载成功 40 | fun onDownLoadSuccess(key: String, path: String) 41 | 42 | // 下载暂停 43 | fun onDownLoadPause(key: String) 44 | 45 | // 下载取消 46 | fun onDownLoadCancel(key: String) 47 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/LogInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import android.os.Handler 4 | import com.allens.moya.config.MoyaConfig 5 | import com.allens.moya.enums.LoggerLevel 6 | import com.allens.moya.tools.MoyaLogTool 7 | import okhttp3.logging.HttpLoggingInterceptor 8 | 9 | /** 10 | * 11 | * @Description: 12 | * @Author: Allens 13 | * @CreateDate: 2019-11-22 14:02 14 | * @Version: 1.0 15 | */ 16 | 17 | //日志拦截器 18 | object LogInterceptor { 19 | fun register(config: MoyaConfig, handler: Handler): HttpLoggingInterceptor { 20 | val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { 21 | override fun log(message: String) { 22 | MoyaLogTool.i(message) 23 | handler.post { 24 | config.logSet.forEach { 25 | it.onLogInterceptorInfo(message) 26 | } 27 | } 28 | } 29 | }) 30 | interceptor.level = LoggerLevel.conversion(config.level) 31 | return interceptor 32 | } 33 | } 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /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=-Xmx2048m -Dfile.encoding=UTF-8 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 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStorage;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt32$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt32$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt32$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt;:$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/CacheNetworkInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import com.allens.moya.config.MoyaConfig 4 | import com.allens.moya.enums.NetWorkCacheType 5 | import com.allens.moya.tools.MoyaLogTool 6 | import okhttp3.Interceptor 7 | import okhttp3.Response 8 | 9 | internal class CacheNetworkInterceptor(private val config: MoyaConfig) : Interceptor { 10 | override fun intercept(chain: Interceptor.Chain): Response { 11 | val time = when (config.cacheNetWorkType) { 12 | NetWorkCacheType.NOCACHE -> { 13 | 0 14 | } 15 | NetWorkCacheType.CACHE_TIME -> { 16 | config.cacheNetworkTimeOut 17 | } 18 | else -> { 19 | 0 20 | } 21 | } 22 | MoyaLogTool.i( 23 | "--> 缓存配置(有网络连接):" + if (time == 0) { 24 | "每次都请求实时数据" 25 | } else { 26 | "$time 秒之后请求数据" 27 | } 28 | ) 29 | return chain.proceed(chain.request()).newBuilder() 30 | // 清除头信息 因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效 31 | .removeHeader("Pragma") 32 | .addHeader("Cache-Control", "max-age=$time") 33 | .build() 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/ParameterInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | 4 | import android.os.Looper 5 | import com.allens.moya.impl.OnDownLoadInterceptor 6 | import com.allens.moya.request.BasicDownLoadRequest 7 | import com.allens.moya.tools.MoyaLogTool 8 | 9 | // 参数校验是否合法 10 | class ParameterInterceptor : OnDownLoadInterceptor { 11 | 12 | override fun onIntercept( 13 | request: BasicDownLoadRequest, 14 | function: (Throwable) -> Unit 15 | ): Boolean { 16 | MoyaLogTool.i("ParameterInterceptor check") 17 | // 在主线程 no 18 | if (Looper.getMainLooper().thread == Thread.currentThread()) { 19 | function(Throwable("work in main thread")) 20 | return false 21 | } 22 | // 下载地址不能是空 23 | if (request.url.isEmpty()) { 24 | function(Throwable("download url is empty")) 25 | return false 26 | } 27 | // 保存路径不合法 28 | if (request.path.isNullOrEmpty()) { 29 | function(Throwable("save file path is null or empty")) 30 | return false 31 | } 32 | // 保存名称不合法 33 | if (request.name.isNullOrEmpty()) { 34 | function(Throwable("save file name is null or empty")) 35 | return false 36 | } 37 | MoyaLogTool.i("ParameterInterceptor pass") 38 | return true 39 | } 40 | } -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/manager/CoroutinesDownLoadManager.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.manager 2 | 3 | import com.allens.moya.manager.DownLoadManagerImpl 4 | import com.allens.moya.impl.OnDownLoadInterceptor 5 | import com.allens.moya_coroutines.impl.ApiService 6 | import com.allens.moya_coroutines.request.CoroutinesDisposable 7 | import com.allens.moya_coroutines.request.CoroutinesDownLoadRequest 8 | import com.allens.moya_coroutines.request.getServiceWithOutLogInterceptor 9 | import kotlinx.coroutines.Dispatchers 10 | import kotlinx.coroutines.launch 11 | import okhttp3.ResponseBody 12 | 13 | object CoroutinesDownLoadManager : DownLoadManagerImpl() { 14 | override fun addInterceptor(): MutableSet { 15 | return mutableSetOf() 16 | } 17 | 18 | 19 | override fun startRequest( 20 | request: CoroutinesDownLoadRequest, 21 | currentLength: Long, 22 | block: (ResponseBody?) -> Unit 23 | ): CoroutinesDisposable { 24 | val job = request.coroutines.launch(Dispatchers.IO) { 25 | val response = getServiceWithOutLogInterceptor(request.manager) 26 | .downloadFile("bytes=$currentLength-", request.url) 27 | val responseBody = response.body() 28 | block(responseBody) 29 | } 30 | return CoroutinesDisposable(job) 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 33 | 34 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/ReceivedCookieInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import com.allens.moya.impl.OnCookieInterceptor 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | 7 | // cookie 拦截器 8 | object ReceivedCookieInterceptor { 9 | fun register(interceptor: OnCookieInterceptor): Interceptor { 10 | return ReceivedCookiesInterceptorImpl(interceptor) 11 | } 12 | } 13 | 14 | 15 | class ReceivedCookiesInterceptorImpl( 16 | private val interceptor: OnCookieInterceptor 17 | ) : Interceptor { 18 | override fun intercept(chain: Interceptor.Chain): Response { 19 | val response = chain.proceed(chain.request()) 20 | // 不是拦截全部 21 | if (!interceptor.isInterceptorAllRequest()) { 22 | val url = response.request.url.toUrl().toString() 23 | if (interceptor.interceptorRequestWithUrl(url)) { 24 | interceptor(response) 25 | } 26 | return response 27 | } 28 | 29 | // 这里获取请求返回的cookie 30 | interceptor(response) 31 | 32 | return response 33 | } 34 | 35 | private fun interceptor(response: Response) { 36 | if (response.headers("Set-Cookie").isNotEmpty()) { 37 | val cookies = HashSet() 38 | for (header in response.headers("Set-Cookie")) { 39 | cookies.add(header) 40 | } 41 | interceptor.onCookies(cookies) 42 | } 43 | } 44 | } 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/request/DownLoadRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.request 2 | 3 | import com.allens.moya.impl.OnDownLoadListener 4 | 5 | 6 | fun DownLoadRequest.getKey(): String { 7 | return this.tag ?: this.url 8 | } 9 | 10 | // 下载请求配置 11 | open class DownLoadRequest { 12 | lateinit var url: String 13 | var path: String? = null 14 | var name: String? = null 15 | var tag: String? = null 16 | var listener: OnDownLoadListener? = null 17 | 18 | class Builder { 19 | private var path: String? = null 20 | private var name: String? = null 21 | private var tag: String? = null 22 | private var listener: OnDownLoadListener? = null 23 | 24 | fun path(path: String) = apply { 25 | this.path = path 26 | } 27 | 28 | fun name(name: String) = apply { 29 | this.name = name 30 | } 31 | 32 | fun tag(tag: String) = apply { 33 | this.tag = tag 34 | } 35 | 36 | fun listener(listener: OnDownLoadListener) = apply { 37 | this.listener = listener 38 | } 39 | 40 | fun build(url: String): DownLoadRequest { 41 | return DownLoadRequest().apply { 42 | this.url = url 43 | this.path = this@Builder.path 44 | this.tag = this@Builder.tag 45 | this.name = this@Builder.name 46 | this.listener = this@Builder.listener 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/result/HttpResult.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.result 2 | 3 | import androidx.annotation.MainThread 4 | 5 | 6 | open class HttpBuilder { 7 | var onSuccess: (data: T) -> Unit = {} 8 | var onError: (Throwable) -> Unit = {} 9 | var onComplete: () -> Unit = {} 10 | } 11 | 12 | 13 | sealed class HttpResult { 14 | 15 | 16 | data class Success(val data: T) : HttpResult() 17 | data class Error(val throwable: Throwable) : HttpResult() 18 | 19 | private var complete: (() -> Unit)? = null 20 | 21 | private var isComplete = false 22 | 23 | // toString 返回结果String 24 | override fun toString(): String { 25 | return when (this) { 26 | is Success<*> -> "Success-> $data" 27 | is Error -> "Error-> ${throwable.message}" 28 | } 29 | } 30 | 31 | 32 | // 返回结果 33 | fun get(): T? { 34 | if (this is Success) { 35 | return data 36 | } 37 | return null 38 | } 39 | 40 | // 请求成功 41 | @MainThread 42 | fun doSuccess(block: (T) -> Unit) = apply { 43 | if (this is Success) { 44 | block(data) 45 | complete?.invoke() 46 | isComplete = true 47 | } 48 | } 49 | 50 | // 请求失败 51 | @MainThread 52 | fun doFailed(block: (Throwable) -> Unit) = apply { 53 | if (this is Error) { 54 | block(throwable) 55 | complete?.invoke() 56 | isComplete = true 57 | } 58 | } 59 | 60 | // 请求完成 61 | @MainThread 62 | fun doComplete(block: () -> Unit) = apply { 63 | if (isComplete) { 64 | block() 65 | } else { 66 | complete = block 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | import com.allens.tea.BuildConfig 2 | import com.allens.tea.Libs 3 | 4 | plugins { 5 | id 'com.android.application' 6 | id 'kotlin-android' 7 | // 导入自定义插件 添加依赖管理 8 | id 'com.allens.plugin' 9 | } 10 | 11 | android { 12 | compileSdkVersion BuildConfig.compileSdkVersion 13 | buildToolsVersion BuildConfig.buildToolsVersion 14 | 15 | defaultConfig { 16 | applicationId "com.allens.tea" 17 | minSdkVersion BuildConfig.minSdkVersion 18 | targetSdkVersion BuildConfig.targetSdkVersion 19 | versionCode BuildConfig.versionCode 20 | versionName BuildConfig.versionName 21 | 22 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 23 | } 24 | 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | buildFeatures { 40 | viewBinding = true 41 | } 42 | } 43 | 44 | dependencies { 45 | 46 | implementation Libs.Kotlin.stdlib 47 | implementation Libs.AndroidX.coreKtx 48 | implementation Libs.AndroidX.appcompat 49 | implementation Libs.material 50 | implementation Libs.AndroidX.constraintlayout 51 | implementation Libs.AndroidX.Activity.activityKtx 52 | implementation Libs.junit 53 | androidTestImplementation Libs.AndroidX.Test.Ext.junit 54 | androidTestImplementation Libs.AndroidX.Test.espressoCore 55 | 56 | 57 | implementation project(Libs.Custom.httpCoroutines) 58 | implementation Libs.Github.viewbinding 59 | } -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/versionPluginjar-classes.txt: -------------------------------------------------------------------------------- 1 | /Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/BuildConfig.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Deps.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Activity.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test$Ext.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX$Test.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$AndroidX.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Custom.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Github.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Google.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Kotlin.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Lifecycle.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup$OkHttp3.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Squareup.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs$Tencent.class:/Users/jhy/Documents/project/android/allens/tea/versionPlugin/build/classes/kotlin/main/com/allens/tea/Libs.class -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/PutRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // put 19 | //============================================================= 20 | suspend fun Request.Builder.executePut(parameter: String): String? = 21 | getService(manager).doPut(parameter, config.heard, config.map).string() 22 | 23 | suspend inline fun Request.Builder.doPut( 24 | parameter: String, 25 | ): HttpResult = execute(manager) { executePut(parameter) } 26 | 27 | 28 | inline fun Request.Builder.doPut( 29 | parameter: String, 30 | crossinline init: HttpBuilder.() -> Unit 31 | ): Disposable = executeDisable(config, manager, init) { 32 | executePut(parameter) 33 | } 34 | 35 | @Deprecated( 36 | message = MoyaMessage.Deprecated, 37 | level = DeprecationLevel.WARNING, 38 | replaceWith = ReplaceWith(MoyaMessage.PUT, imports = arrayOf(MoyaMessage.IMPORTS)) 39 | ) 40 | inline fun Request.Builder.doPutBlock( 41 | parameter: String, 42 | crossinline block: suspend (HttpResult) -> Unit 43 | ): Disposable = executeDisable(config, manager, block) { 44 | executePut(parameter) 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/DeleteRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // delete 19 | //============================================================= 20 | suspend fun Request.Builder.executeDelete(parameter: String): String? = 21 | getService(manager).doDelete(parameter, config.heard, config.map).string() 22 | 23 | suspend inline fun Request.Builder.doDelete( 24 | parameter: String, 25 | ): HttpResult = execute(manager) { executeDelete(parameter) } 26 | 27 | 28 | inline fun Request.Builder.doDelete( 29 | parameter: String, 30 | crossinline init: HttpBuilder.() -> Unit 31 | ): Disposable = executeDisable(config, manager, init) { 32 | executeDelete(parameter) 33 | } 34 | 35 | @Deprecated( 36 | message = MoyaMessage.Deprecated, 37 | level = DeprecationLevel.WARNING, 38 | replaceWith = ReplaceWith(MoyaMessage.DELETE, imports = arrayOf(MoyaMessage.IMPORTS)) 39 | ) 40 | inline fun Request.Builder.doDeleteBlock( 41 | parameter: String, 42 | crossinline block: suspend (HttpResult) -> Unit 43 | ): Disposable = executeDisable(config, manager, block) { 44 | executeDelete(parameter) 45 | } 46 | 47 | -------------------------------------------------------------------------------- /moya/build.gradle: -------------------------------------------------------------------------------- 1 | import com.allens.tea.BuildConfig 2 | import com.allens.tea.Libs 3 | 4 | plugins { 5 | id 'com.android.library' 6 | id 'kotlin-android' 7 | id 'com.allens.plugin' 8 | } 9 | 10 | android { 11 | compileSdkVersion BuildConfig.compileSdkVersion 12 | buildToolsVersion BuildConfig.buildToolsVersion 13 | 14 | defaultConfig { 15 | minSdkVersion BuildConfig.minSdkVersion 16 | targetSdkVersion BuildConfig.targetSdkVersion 17 | 18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 19 | consumerProguardFiles "consumer-rules.pro" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | } 35 | sourceSets { 36 | main { 37 | java { 38 | java.srcDirs += 'src/main/kotlin' 39 | } 40 | } 41 | } 42 | } 43 | 44 | dependencies { 45 | 46 | implementation Libs.Kotlin.stdlib 47 | implementation Libs.AndroidX.coreKtx 48 | implementation Libs.AndroidX.appcompat 49 | implementation Libs.material 50 | implementation Libs.AndroidX.constraintlayout 51 | implementation Libs.junit 52 | androidTestImplementation Libs.AndroidX.Test.Ext.junit 53 | androidTestImplementation Libs.AndroidX.Test.espressoCore 54 | 55 | 56 | implementation Libs.Squareup.retrofit2 57 | implementation Libs.Squareup.OkHttp3.loggingInterceptor 58 | implementation Libs.Tencent.mmkv 59 | implementation Libs.Google.gson 60 | implementation Libs.persistentCookieJar 61 | } -------------------------------------------------------------------------------- /moya-coroutines/build.gradle: -------------------------------------------------------------------------------- 1 | import com.allens.tea.BuildConfig 2 | import com.allens.tea.Libs 3 | 4 | plugins { 5 | id 'com.android.library' 6 | id 'kotlin-android' 7 | id 'com.allens.plugin' 8 | } 9 | 10 | android { 11 | compileSdkVersion BuildConfig.compileSdkVersion 12 | buildToolsVersion BuildConfig.buildToolsVersion 13 | 14 | defaultConfig { 15 | minSdkVersion BuildConfig.minSdkVersion 16 | targetSdkVersion BuildConfig.targetSdkVersion 17 | versionCode 1 18 | versionName "1.0" 19 | 20 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 21 | consumerProguardFiles "consumer-rules.pro" 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | kotlinOptions { 35 | jvmTarget = '1.8' 36 | } 37 | sourceSets { 38 | main { 39 | java { 40 | java.srcDirs += 'src/main/kotlin' 41 | } 42 | } 43 | } 44 | } 45 | 46 | dependencies { 47 | 48 | implementation Libs.Kotlin.stdlib 49 | implementation Libs.AndroidX.coreKtx 50 | implementation Libs.AndroidX.appcompat 51 | implementation Libs.material 52 | implementation Libs.AndroidX.constraintlayout 53 | implementation Libs.junit 54 | androidTestImplementation Libs.AndroidX.Test.Ext.junit 55 | androidTestImplementation Libs.AndroidX.Test.espressoCore 56 | 57 | 58 | implementation Libs.Google.gson 59 | implementation Libs.Squareup.retrofit2 60 | implementation Libs.Lifecycle.viewModelKtx 61 | implementation Libs.Lifecycle.livedataKtx 62 | implementation Libs.Lifecycle.runtimeKtx 63 | 64 | api project(Libs.Custom.http) 65 | 66 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/DynamicBaseUrlInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import com.allens.moya.enums.DynamicHeard 4 | import okhttp3.HttpUrl 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | import java.net.URL 8 | 9 | // 动态修改baseUrl 10 | object DynamicBaseUrlInterceptor : Interceptor { 11 | override fun intercept(chain: Interceptor.Chain): Response { 12 | 13 | var request = chain.request() 14 | val headers = request.headers 15 | 16 | if (headers.size > 0) { 17 | val url = headers[DynamicHeard.DYNAMIC_URL] 18 | if (url != null) { 19 | val httpUrl = request.url 20 | val newBuilder = httpUrl.newBuilder() 21 | checkBaseUrl(url, newBuilder) 22 | setNewHost(url, newBuilder) 23 | request = request.newBuilder() 24 | .removeHeader(DynamicHeard.DYNAMIC_URL) 25 | .url(newBuilder.build()) 26 | .build() 27 | return chain.proceed(request) 28 | } 29 | } 30 | return chain.proceed(request) 31 | } 32 | 33 | private fun setNewHost( 34 | newUrl: String, 35 | newBuilder: HttpUrl.Builder 36 | ) { 37 | try { 38 | val url = URL(newUrl) 39 | val domain: String = url.host 40 | newBuilder.host(domain) 41 | } catch (throwable: Throwable) { 42 | throw Throwable("$newUrl is invalid base url ,please check this base url") 43 | } 44 | } 45 | 46 | private fun checkBaseUrl( 47 | newUrl: String, 48 | newBuilder: HttpUrl.Builder 49 | ) { 50 | when { 51 | newUrl.startsWith("https") -> { 52 | newBuilder.scheme("https") 53 | } 54 | newUrl.startsWith("http") -> { 55 | newBuilder.scheme("http") 56 | } 57 | else -> { 58 | throw Throwable("$newUrl is not https or http , please check this base url") 59 | } 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/GetRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // get 19 | //============================================================= 20 | suspend fun Request.Builder.executeGet(parameter: String): String? { 21 | val baseUrl = manager.retrofit.baseUrl().toString() 22 | var getUrl: String = baseUrl + parameter 23 | if (config.map.size > 0) { 24 | val param: String = UrlTool.prepareParam(config.map) 25 | if (param.trim().isNotEmpty()) { 26 | getUrl += "?$param" 27 | } 28 | } 29 | return getService(manager).doGet(config.heard, getUrl).string() 30 | } 31 | 32 | suspend inline fun Request.Builder.doGet( 33 | parameter: String, 34 | ): HttpResult = execute(manager) { executeGet(parameter) } 35 | 36 | 37 | inline fun Request.Builder.doGet( 38 | parameter: String, 39 | crossinline init: HttpBuilder.() -> Unit 40 | ): Disposable = executeDisable(config, manager, init) { 41 | executeGet(parameter) 42 | } 43 | 44 | @Deprecated( 45 | message = MoyaMessage.Deprecated, 46 | level = DeprecationLevel.WARNING, 47 | replaceWith = ReplaceWith(MoyaMessage.GET, imports = arrayOf(MoyaMessage.IMPORTS)) 48 | ) 49 | inline fun Request.Builder.doGetBlock( 50 | parameter: String, 51 | crossinline block: suspend (HttpResult) -> Unit 52 | ): Disposable = executeDisable(config, manager, block) { 53 | executeGet(parameter) 54 | } 55 | 56 | -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/impl/ApiService.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.impl 2 | 3 | import okhttp3.RequestBody 4 | import okhttp3.ResponseBody 5 | import retrofit2.Response 6 | import retrofit2.http.* 7 | 8 | 9 | /** 10 | * 11 | * @Description: 12 | * @Author: Allens 13 | * @CreateDate: 2019-11-22 11:47 14 | * @Version: 1.0 15 | */ 16 | interface ApiService { 17 | 18 | @GET 19 | suspend fun doGet( 20 | @HeaderMap headers: HashMap, 21 | @Url url: String 22 | ): Response 23 | 24 | @FormUrlEncoded 25 | @POST("{path}") 26 | suspend fun doPost( 27 | @Path( 28 | value = "path", 29 | encoded = true 30 | ) urlPath: String, 31 | @HeaderMap headers: HashMap, 32 | @FieldMap map: HashMap 33 | ): Response 34 | 35 | 36 | @POST("{path}") 37 | suspend fun doBody( 38 | @Path( 39 | value = "path", 40 | encoded = true 41 | ) urlPath: String, @HeaderMap headers: HashMap, @Body body: RequestBody 42 | ): Response 43 | 44 | 45 | @DELETE 46 | suspend fun doDelete( 47 | @Url url: String, 48 | @HeaderMap headers: HashMap, 49 | @QueryMap maps: Map 50 | ): Response 51 | 52 | 53 | @PUT 54 | suspend fun doPut( 55 | @Url url: String, 56 | @HeaderMap headers: HashMap, 57 | @FieldMap maps: HashMap 58 | ): Response 59 | 60 | @Streaming 61 | @GET 62 | suspend fun downloadFile( 63 | @Header("RANGE") start: String, 64 | @Url url: String 65 | ): Response 66 | 67 | 68 | @Multipart 69 | @POST 70 | suspend fun upLoad( 71 | @Url url: String, 72 | @HeaderMap headers: HashMap, 73 | @QueryMap maps: Map, 74 | @PartMap files: Map 75 | ): Response 76 | 77 | } -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/UploadRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // 上传 19 | //============================================================= 20 | suspend fun Request.Builder.executeUpLoad( 21 | parameter: String, 22 | listener: UpLoadBuilder 23 | ): String? { 24 | for ((key, value) in config.files) { 25 | config.files[key] = 26 | ProgressRequestBody( 27 | value.getRequestBody(), 28 | progressBlock = { bytesWriting, contentLength, progress -> 29 | MoyaLogTool.i("上传进度:$progress $bytesWriting/$contentLength") 30 | manager.handler.post { 31 | listener.onProgress(progress, bytesWriting, contentLength) 32 | } 33 | }, 34 | errorBlock = { 35 | MoyaLogTool.i("上传异常:${it.message}") 36 | manager.handler.post { 37 | listener.onError(it) 38 | } 39 | }) 40 | } 41 | return getServiceWithOutLogInterceptor(manager).upLoad( 42 | parameter, 43 | config.heard, 44 | config.map, 45 | config.files 46 | ).string() 47 | } 48 | 49 | 50 | inline fun Request.Builder.doUpLoad( 51 | parameter: String, 52 | crossinline init: UpLoadBuilder.() -> Unit 53 | ): Disposable { 54 | val builder = UpLoadBuilder().apply(init) 55 | return executeUpLoadDisable(config.viewModel, config.owner, manager, builder) { 56 | executeUpLoad(parameter, builder) 57 | } 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/request/ProgressRequestBody.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.request 2 | 3 | 4 | import androidx.annotation.Nullable 5 | import okhttp3.MediaType 6 | import okhttp3.RequestBody 7 | import okio.* 8 | import java.io.IOException 9 | 10 | class ProgressRequestBody( 11 | private val requestBody: RequestBody, 12 | val progressBlock: (( 13 | bytesWriting: Long, 14 | contentLength: Long, 15 | progress: Int 16 | ) -> Unit)? = null, 17 | val errorBlock: ((Throwable) -> Unit)? = null 18 | ) : RequestBody() { 19 | private var bufferedSink: BufferedSink? = null 20 | 21 | private var lastProgress: Int = 0 22 | 23 | 24 | fun getRequestBody(): RequestBody { 25 | return requestBody 26 | } 27 | 28 | @Nullable 29 | override fun contentType(): MediaType? { 30 | return requestBody.contentType() 31 | } 32 | 33 | @Throws(IOException::class) 34 | override fun contentLength(): Long { 35 | return requestBody.contentLength() 36 | } 37 | 38 | // 关键方法 39 | override fun writeTo(sink: BufferedSink) { 40 | try { 41 | if (null == bufferedSink) bufferedSink = sink(sink).buffer() 42 | requestBody.writeTo(bufferedSink!!) 43 | // 必须调用flush,否则最后一部分数据可能不会被写入 44 | bufferedSink?.flush() 45 | } catch (t: Throwable) { 46 | errorBlock?.let { it(t) } 47 | } 48 | } 49 | 50 | private fun sink(sink: Sink): Sink { 51 | return object : ForwardingSink(sink) { 52 | var bytesWriting = 0L 53 | var contentLength = 0L 54 | 55 | @Throws(IOException::class) 56 | override fun write(source: Buffer, byteCount: Long) { 57 | super.write(source, byteCount) 58 | if (0L == contentLength) contentLength = contentLength() 59 | bytesWriting += byteCount 60 | // 调用接口,把上传文件的进度传过去 61 | val progress = (bytesWriting.toFloat() / contentLength * 100).toInt() // 计算百分比 62 | if (lastProgress != progress) { 63 | lastProgress = progress 64 | progressBlock?.let { it(bytesWriting, contentLength, progress) } 65 | } 66 | } 67 | } 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/enums/TimeUnitEnum.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.enums 2 | 3 | import android.os.Build 4 | import java.util.concurrent.TimeUnit 5 | 6 | 7 | class DynamicHeard { 8 | companion object { 9 | private val TODO_HEARD = Build.BRAND + "_" + Build.MODEL + "_" 10 | val DYNAMIC_URL = TODO_HEARD + "DYNAMIC_URL" 11 | val DYNAMIC_CONNECT_TIME_OUT = TODO_HEARD + "DYNAMIC_CONNECT_TIME_OUT" 12 | val DYNAMIC_CONNECT_TIME_OUT_TimeUnit = TODO_HEARD + "DYNAMIC_CONNECT_TIME_OUT_TimeUnit" 13 | val DYNAMIC_WRITE_TIME_OUT = TODO_HEARD + "DYNAMIC_WRITE_TIME_OUT" 14 | val DYNAMIC_WRITE_TIME_OUT_TimeUnit = TODO_HEARD + "DYNAMIC_WRITE_TIME_OUT_TimeUnit" 15 | val DYNAMIC_READ_TIME_OUT = TODO_HEARD + "DYNAMIC_READ_TIME_OUT" 16 | val DYNAMIC_READ_TIME_OUT_TimeUnit = TODO_HEARD + "DYNAMIC_READ_TIME_OUT_TimeUnit" 17 | 18 | fun timeUnitConvert(timeUnit: TimeUnit): TimeUnitEnum { 19 | return when (timeUnit) { 20 | TimeUnit.NANOSECONDS -> TimeUnitEnum.NANOSECONDS 21 | TimeUnit.MICROSECONDS -> TimeUnitEnum.MICROSECONDS 22 | TimeUnit.MILLISECONDS -> TimeUnitEnum.MILLISECONDS 23 | TimeUnit.SECONDS -> TimeUnitEnum.SECONDS 24 | TimeUnit.MINUTES -> TimeUnitEnum.MINUTES 25 | TimeUnit.HOURS -> TimeUnitEnum.HOURS 26 | TimeUnit.DAYS -> TimeUnitEnum.DAYS 27 | else -> TimeUnitEnum.MILLISECONDS 28 | } 29 | } 30 | 31 | fun convertTimeUnit(info: String?): TimeUnit { 32 | return when (info) { 33 | "NANOSECONDS" -> TimeUnit.NANOSECONDS 34 | "MICROSECONDS" -> TimeUnit.MICROSECONDS 35 | "MILLISECONDS" -> TimeUnit.MILLISECONDS 36 | "SECONDS" -> TimeUnit.SECONDS 37 | "MINUTES" -> TimeUnit.MINUTES 38 | "HOURS" -> TimeUnit.HOURS 39 | "DAYS" -> TimeUnit.DAYS 40 | else -> TimeUnit.MILLISECONDS 41 | } 42 | } 43 | } 44 | } 45 | 46 | enum class TimeUnitEnum(val info: String, val timeUnit: TimeUnit) { 47 | NANOSECONDS("NANOSECONDS", TimeUnit.NANOSECONDS), 48 | MICROSECONDS("MICROSECONDS", TimeUnit.MICROSECONDS), 49 | MILLISECONDS("MILLISECONDS", TimeUnit.MILLISECONDS), 50 | SECONDS("SECONDS", TimeUnit.SECONDS), 51 | MINUTES("MINUTES", TimeUnit.MINUTES), 52 | HOURS("HOURS", TimeUnit.HOURS), 53 | DAYS("DAYS", TimeUnit.DAYS), 54 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/config/MoyaConfig.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.config 2 | 3 | import com.allens.moya.enums.NoNetWorkCacheType 4 | import com.allens.moya.enums.LoggerLevel 5 | import com.allens.moya.enums.NetWorkCacheType 6 | import com.allens.moya.impl.OnCookieInterceptor 7 | import com.allens.moya.impl.OnLogInterceptor 8 | import okhttp3.Interceptor 9 | import retrofit2.CallAdapter 10 | import retrofit2.Converter 11 | import java.util.concurrent.TimeUnit 12 | 13 | 14 | /*** 15 | * Moya 网络配置 16 | * 17 | */ 18 | data class MoyaConfig( 19 | 20 | // baseUrl 21 | var baseUrl: String = DefaultConfig.DEFAULT_BASE_URL, 22 | 23 | // 连接超时等 24 | var connectTime: Long = DefaultConfig.DEFAULT_TIME_OUT, 25 | var connectTimeTimeUnit: TimeUnit = TimeUnit.SECONDS, 26 | 27 | // 写超时 28 | var readTime: Long = DefaultConfig.DEFAULT_TIME_OUT, 29 | var readTimeTimeUnit: TimeUnit = TimeUnit.SECONDS, 30 | 31 | // 读超时 32 | var writeTime: Long = DefaultConfig.DEFAULT_TIME_OUT, 33 | var writeTimeTimeUnit: TimeUnit = TimeUnit.SECONDS, 34 | 35 | // 是否重试 36 | var retryOnConnectionFailure: Boolean = DefaultConfig.DEFAULT_RETRY, 37 | 38 | // 日志的级别 39 | var level: LoggerLevel = DefaultConfig.DEFAULT_LEVEL, 40 | 41 | // 日志的拦截器 42 | var logSet: MutableSet = mutableSetOf(), 43 | 44 | // cookie的拦截器 45 | var cookieSet: MutableSet = mutableSetOf(), 46 | 47 | // 自定义的拦截器 48 | var interceptor: MutableSet = mutableSetOf(), 49 | 50 | // 配置通用的请求头 51 | var heardMap: HashMap = HashMap(), 52 | 53 | // 添加自定的转换器 54 | var converterFactorySet: MutableSet = mutableSetOf(), 55 | 56 | // 添加自定义的适配器 57 | var callAdapterFactorySet: MutableSet = mutableSetOf(), 58 | 59 | // 有网时候的缓存策略 默认无缓存策略 60 | var cacheNetWorkType: NetWorkCacheType = NetWorkCacheType.NONE, 61 | 62 | // 无网时候的缓存策略 默认无缓存策略 63 | var cacheNoNewWorkType: NoNetWorkCacheType = NoNetWorkCacheType.NONE, 64 | 65 | // 有网时:特定时间之后请求数据;(比如:特定时间为20s) 默认20 66 | var cacheNetworkTimeOut: Int = DefaultConfig.DEFAULT_CACHE_NETWORK_TIMEOUT, 67 | 68 | // 无网时:特定时间之前请求有网请求好的数据;((比如:特定时间为30天) 默认30 天 单位(秒) 69 | var cacheNoNetworkTimeOut: Int = DefaultConfig.DEFAULT_NO_CACHE_NETWORK_TIMEOUT, 70 | 71 | // 缓存大小 10M 72 | var cacheSize: Int = DefaultConfig.DEFAULT_CACHE_SIZE, 73 | 74 | // 缓存位置 75 | var cachePath: String = DefaultConfig.DEFAULT_CACHE_PATH, 76 | ) 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /versionPlugin/src/main/java/com/allens/tea/Dependencies.kt: -------------------------------------------------------------------------------- 1 | package com.allens.tea 2 | 3 | object BuildConfig { 4 | const val compileSdkVersion = 30 5 | const val buildToolsVersion = "30.0.3" 6 | const val minSdkVersion = 21 7 | const val targetSdkVersion = 30 8 | const val versionCode = 1 9 | const val versionName = "1.0" 10 | } 11 | 12 | object Libs { 13 | 14 | const val junit = "junit:junit:4.+" 15 | const val material = "com.google.android.material:material:1.3.0" 16 | 17 | 18 | //cookie 19 | const val persistentCookieJar = "com.github.franmontiel:PersistentCookieJar:v1.0.1" 20 | 21 | 22 | object Kotlin { 23 | private const val version = "1.5.0" 24 | const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib:$version" 25 | } 26 | 27 | object AndroidX { 28 | const val appcompat = "androidx.appcompat:appcompat:1.3.0" 29 | const val coreKtx = "androidx.core:core-ktx:1.5.0" 30 | const val constraintlayout = "androidx.constraintlayout:constraintlayout:2.0.4" 31 | 32 | object Activity { 33 | private const val version = "1.2.3" 34 | const val activityKtx = "androidx.activity:activity-ktx:$version" 35 | } 36 | 37 | object Test { 38 | object Ext { 39 | private const val version = "1.1.2" 40 | const val junit = "androidx.test.ext:junit-ktx:$version" 41 | } 42 | 43 | const val espressoCore = "androidx.test.espresso:espresso-core:3.3.0" 44 | } 45 | } 46 | 47 | object Squareup { 48 | const val retrofit2 = "com.squareup.retrofit2:retrofit:2.9.0" 49 | 50 | object OkHttp3 { 51 | const val loggingInterceptor = "com.squareup.okhttp3:logging-interceptor:4.8.1" 52 | } 53 | } 54 | 55 | object Google { 56 | const val gson = "com.google.code.gson:gson:2.8.6" 57 | } 58 | 59 | object Tencent { 60 | const val mmkv = "com.tencent:mmkv-static:1.2.8" 61 | } 62 | 63 | 64 | object Lifecycle { 65 | private const val version = "2.3.1" 66 | const val livedataKtx = "androidx.lifecycle:lifecycle-livedata-ktx:$version" 67 | const val viewModelKtx = "androidx.lifecycle:lifecycle-viewmodel-ktx:$version" 68 | const val runtimeKtx = "androidx.lifecycle:lifecycle-runtime-ktx:$version" 69 | } 70 | 71 | object Custom { 72 | const val http = ":moya" 73 | const val httpCoroutines = ":moya-coroutines" 74 | } 75 | 76 | object Github { 77 | const val viewbinding = "com.github.DylanCaiCoding.ViewBindingKTX:viewbinding-ktx:1.2.0" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/DownLoadRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // 下载 19 | //============================================================= 20 | suspend fun Request.Builder.doDownLoad( 21 | request: DownLoadRequest, 22 | init: (DownLoadBuilder.() -> Unit)? = null 23 | ) { 24 | withContext(Dispatchers.IO) { 25 | val coroutinesDownLoadRequest = convertToCoroutinesRequest(request, this) 26 | val data = CoroutinesDownLoadManager.startDownLoad(coroutinesDownLoadRequest) 27 | withContext(Dispatchers.Main) { 28 | data.liveData?.observerState( 29 | manager = CoroutinesDownLoadManager, 30 | config = config, 31 | request = coroutinesDownLoadRequest, 32 | init = init 33 | ) 34 | } 35 | } 36 | } 37 | 38 | private fun Request.Builder.convertToCoroutinesRequest( 39 | request: DownLoadRequest, 40 | scope: CoroutineScope? = null 41 | ): CoroutinesDownLoadRequest { 42 | return CoroutinesDownLoadRequest().also { 43 | if (scope != null) { 44 | it.coroutines = scope 45 | } 46 | it.url = request.url 47 | it.listener = request.listener 48 | it.name = request.name 49 | it.tag = request.tag 50 | it.path = request.path 51 | it.manager = manager 52 | } 53 | } 54 | 55 | //如果在请求的时候没有tag 则使用url 作为key 56 | fun Request.Builder.doCancelDownLoad(request: DownLoadRequest) { 57 | CoroutinesDownLoadManager.cancel(convertToCoroutinesRequest(request)) 58 | } 59 | 60 | //暂停某一个请求的下载 61 | fun Request.Builder.doPauseDownLoad(request: DownLoadRequest) { 62 | CoroutinesDownLoadManager.pause(convertToCoroutinesRequest(request)) 63 | } 64 | 65 | 66 | //全部取消下载 67 | fun Request.Builder.doDownLoadCancelAll() { 68 | CoroutinesDownLoadManager.cancelAll() 69 | } 70 | 71 | //全部终止下载 72 | fun Request.Builder.doDownLoadPauseAll() { 73 | CoroutinesDownLoadManager.pauseAll() 74 | } 75 | 76 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/DynamicTimeoutInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import com.allens.moya.enums.DynamicHeard 4 | import com.allens.moya.tools.MoyaLogTool 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | 8 | 9 | // 动态设置接口请求超时时间 10 | object DynamicTimeoutInterceptor : Interceptor { 11 | override fun intercept(chain: Interceptor.Chain): Response { 12 | val request = chain.request() 13 | val headers = request.headers 14 | 15 | var newChain = chain 16 | if (headers.size > 0) { 17 | 18 | 19 | val readTimeOut = headers[DynamicHeard.DYNAMIC_READ_TIME_OUT] 20 | if (readTimeOut != null) { 21 | check(readTimeOut) 22 | val timeUnit = 23 | DynamicHeard.convertTimeUnit(headers[DynamicHeard.DYNAMIC_READ_TIME_OUT_TimeUnit]) 24 | MoyaLogTool.i("修改 read time out $readTimeOut") 25 | newChain = 26 | newChain.withReadTimeout(readTimeOut.toInt(), timeUnit) 27 | } 28 | 29 | 30 | val writeTimeOut = headers[DynamicHeard.DYNAMIC_WRITE_TIME_OUT] 31 | if (writeTimeOut != null) { 32 | check(writeTimeOut) 33 | val timeUnit = 34 | DynamicHeard.convertTimeUnit(headers[DynamicHeard.DYNAMIC_WRITE_TIME_OUT_TimeUnit]) 35 | MoyaLogTool.i("修改 write time out $writeTimeOut") 36 | newChain = 37 | newChain.withWriteTimeout(writeTimeOut.toInt(), timeUnit) 38 | } 39 | 40 | 41 | val connectTimeOut = headers[DynamicHeard.DYNAMIC_CONNECT_TIME_OUT] 42 | if (connectTimeOut != null) { 43 | check(connectTimeOut) 44 | val timeUnit = 45 | DynamicHeard.convertTimeUnit(headers[DynamicHeard.DYNAMIC_CONNECT_TIME_OUT_TimeUnit]) 46 | MoyaLogTool.i("修改 connect time out $connectTimeOut") 47 | newChain = 48 | newChain.withConnectTimeout(connectTimeOut.toInt(), timeUnit) 49 | } 50 | } 51 | val newBuilder = request.newBuilder() 52 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_READ_TIME_OUT) 53 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_READ_TIME_OUT_TimeUnit) 54 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_CONNECT_TIME_OUT) 55 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_CONNECT_TIME_OUT_TimeUnit) 56 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_WRITE_TIME_OUT) 57 | newBuilder.removeHeader(DynamicHeard.DYNAMIC_WRITE_TIME_OUT_TimeUnit) 58 | return newChain.proceed(newBuilder.build()) 59 | } 60 | 61 | private fun check(timeout: String) { 62 | if (timeout.toLong() < 0) { 63 | throw Throwable("time out must > 0 ,please check DynamicTimeout") 64 | } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/request/Request.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.request 2 | 3 | import androidx.lifecycle.LifecycleOwner 4 | import androidx.lifecycle.ViewModel 5 | import com.allens.moya.enums.DynamicHeard 6 | import com.allens.moya.manager.HttpManager 7 | import com.allens.moya.tools.MoyaLogTool 8 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 9 | import okhttp3.RequestBody 10 | import okhttp3.RequestBody.Companion.asRequestBody 11 | import java.io.File 12 | import java.util.HashMap 13 | import java.util.concurrent.TimeUnit 14 | 15 | class Request { 16 | class Builder constructor(val manager: HttpManager) { 17 | 18 | // 配置信息 19 | val config = Config() 20 | 21 | class Config { 22 | val heard = HashMap() 23 | val map = HashMap() 24 | val files = HashMap() 25 | var owner: LifecycleOwner? = null 26 | var viewModel: ViewModel? = null 27 | } 28 | 29 | // 添加请求头 30 | fun heard(key: String, value: String) = apply { 31 | config.heard[key] = value 32 | } 33 | 34 | // 添加请求参数 35 | fun parameter(key: String, value: Any) = apply { 36 | config.map[key] = value 37 | } 38 | 39 | fun lifecycle(lifecycle: LifecycleOwner?) = apply { 40 | config.owner = lifecycle 41 | } 42 | 43 | fun viewModel(viewModel: ViewModel) = apply { 44 | config.viewModel = viewModel 45 | } 46 | 47 | // 动态切换请求的地址 48 | fun baseUrl(url: String) = apply { 49 | heard(DynamicHeard.DYNAMIC_URL, url) 50 | } 51 | 52 | // 动态切换connect time 53 | fun connectTimeOut(timeout: Int, timeUnit: TimeUnit = TimeUnit.MILLISECONDS) = apply { 54 | heard(DynamicHeard.DYNAMIC_CONNECT_TIME_OUT, timeout.toString()) 55 | heard( 56 | DynamicHeard.DYNAMIC_CONNECT_TIME_OUT_TimeUnit, 57 | DynamicHeard.timeUnitConvert(timeUnit).info 58 | ) 59 | } 60 | 61 | // 动态切换write time 62 | fun writeTimeOut(timeout: Int, timeUnit: TimeUnit = TimeUnit.MILLISECONDS) = apply { 63 | heard(DynamicHeard.DYNAMIC_WRITE_TIME_OUT, timeout.toString()) 64 | heard( 65 | DynamicHeard.DYNAMIC_WRITE_TIME_OUT_TimeUnit, 66 | DynamicHeard.timeUnitConvert(timeUnit).info 67 | ) 68 | } 69 | 70 | // 动态切换read time 71 | fun readTimeOut(timeout: Int, timeUnit: TimeUnit = TimeUnit.MILLISECONDS) = apply { 72 | heard(DynamicHeard.DYNAMIC_READ_TIME_OUT, timeout.toString()) 73 | heard( 74 | DynamicHeard.DYNAMIC_READ_TIME_OUT_TimeUnit, 75 | DynamicHeard.timeUnitConvert(timeUnit).info 76 | ) 77 | } 78 | 79 | //添加上传的文件 80 | fun file(key: String, file: File) = apply { 81 | val fileBody: RequestBody = 82 | file.asRequestBody("multipart/form-data".toMediaTypeOrNull()) 83 | config.files[key] = ProgressRequestBody(fileBody) 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/PostRequest.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import com.allens.moya.livedata.observerState 4 | import com.allens.moya.message.MoyaMessage 5 | import com.allens.moya.request.* 6 | import com.allens.moya.result.* 7 | import com.allens.moya.tools.MoyaLogTool 8 | import com.allens.moya.tools.UrlTool 9 | import com.allens.moya_coroutines.manager.CoroutinesDownLoadManager 10 | import kotlinx.coroutines.CoroutineScope 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.withContext 13 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 14 | import okhttp3.RequestBody.Companion.toRequestBody 15 | 16 | 17 | //============================================================= 18 | // post 表单提交 19 | //============================================================= 20 | suspend fun Request.Builder.executePost(parameter: String): String? = 21 | getService(manager).doPost(parameter, config.heard, config.map).string() 22 | 23 | suspend inline fun Request.Builder.doPost( 24 | parameter: String, 25 | ): HttpResult = execute(manager) { executePost(parameter) } 26 | 27 | 28 | inline fun Request.Builder.doPost( 29 | parameter: String, 30 | crossinline init: HttpBuilder.() -> Unit 31 | ): Disposable = executeDisable(config, manager, init) { 32 | executePost(parameter) 33 | } 34 | 35 | @Deprecated( 36 | message = MoyaMessage.Deprecated, 37 | level = DeprecationLevel.WARNING, 38 | replaceWith = ReplaceWith(MoyaMessage.POST, imports = arrayOf(MoyaMessage.IMPORTS)) 39 | ) 40 | inline fun Request.Builder.doPostBlock( 41 | parameter: String, 42 | crossinline block: suspend (HttpResult) -> Unit 43 | ): Disposable = executeDisable(config, manager, block) { 44 | executePost(parameter) 45 | } 46 | 47 | 48 | //============================================================= 49 | // post json 的方式请求 50 | //============================================================= 51 | suspend fun Request.Builder.executeBody(parameter: String): String? { 52 | val requestBody = manager.gson.toJson(config.map) 53 | .toRequestBody("application/json".toMediaTypeOrNull()) 54 | return getService(manager).doBody(parameter, config.heard, requestBody).string() 55 | } 56 | 57 | suspend inline fun Request.Builder.doBody( 58 | parameter: String, 59 | ): HttpResult = execute(manager) { executeBody(parameter) } 60 | 61 | 62 | inline fun Request.Builder.doBody( 63 | parameter: String, 64 | crossinline init: HttpBuilder.() -> Unit 65 | ): Disposable = executeDisable(config, manager, init) { 66 | executeBody(parameter) 67 | } 68 | 69 | 70 | @Deprecated( 71 | message = MoyaMessage.Deprecated, 72 | level = DeprecationLevel.WARNING, 73 | replaceWith = ReplaceWith(MoyaMessage.BODY, imports = arrayOf(MoyaMessage.IMPORTS)) 74 | ) 75 | inline fun Request.Builder.doBodyBlock( 76 | parameter: String, 77 | crossinline block: suspend (HttpResult) -> Unit 78 | ): Disposable = executeDisable(config, manager, block) { 79 | executeBody(parameter) 80 | } 81 | 82 | -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/lookups.tab.values.at: -------------------------------------------------------------------------------- 1 | /Header Record For PersistentHashMapValueStorage               $  2 |  3 |  4 |  5 |  6 | ( 7 |  8 |  9 |  10 |  11 |  12 | , 13 |  14 | $ 15 | $ 16 | $ 17 |  18 | 0 19 |  20 | ( 21 | ( 22 | ( 23 |   24 | 4 25 |  26 | , 27 | , 28 | , 29 |    30 | 8 31 | $ 32 | 0 33 | 0 34 | 0 35 |  $ 36 | < 37 | ( 38 | 4 39 | 4 40 | 4 41 |  ( 42 | @ 43 | , 44 | 8 45 | 8 46 | 8 47 |  , 48 | D 49 | 0 50 | < 51 | < 52 | < 53 |  0 54 | H 55 |  -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/interceptor/CacheInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.interceptor 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.NetworkCapabilities 6 | import android.os.Build 7 | import androidx.annotation.RequiresApi 8 | import com.allens.moya.config.MoyaConfig 9 | import com.allens.moya.enums.NoNetWorkCacheType 10 | import com.allens.moya.tools.MoyaLogTool 11 | import okhttp3.CacheControl 12 | import okhttp3.Interceptor 13 | import okhttp3.Request 14 | import okhttp3.Response 15 | import java.util.concurrent.TimeUnit 16 | 17 | 18 | internal class CacheInterceptor(private val context: Context, private val httpConfig: MoyaConfig) : 19 | Interceptor { 20 | override fun intercept(chain: Interceptor.Chain): Response { 21 | val resp: Response 22 | val req: Request = if (isNetworkAvailable(context)) { 23 | chain.request() 24 | .newBuilder() 25 | .build() 26 | } else { 27 | // 无网络,检查*天内的缓存,即使是过期的缓存 28 | val time = when (httpConfig.cacheNoNewWorkType) { 29 | NoNetWorkCacheType.NO_TIMEOUT -> { 30 | Integer.MAX_VALUE 31 | } 32 | NoNetWorkCacheType.HAS_TIMEOUT -> { 33 | httpConfig.cacheNoNetworkTimeOut 34 | } 35 | else -> { 36 | 0 37 | } 38 | } 39 | MoyaLogTool.i( 40 | "--> 缓存配置(无网络连接):" + if (time != httpConfig.cacheNoNetworkTimeOut) { 41 | "无限时请求有网请求好的数据" 42 | } else { 43 | "$time 秒请求有网请求好的数据" 44 | } 45 | ) 46 | chain.request().newBuilder() 47 | .cacheControl( 48 | CacheControl.Builder() 49 | .onlyIfCached() 50 | .maxStale(time, TimeUnit.SECONDS) 51 | .build() 52 | ) 53 | .build() 54 | } 55 | resp = chain.proceed(req) 56 | return resp.newBuilder().build() 57 | } 58 | } 59 | 60 | 61 | // 判断是否连接 62 | private fun isNetworkAvailable(context: Context): Boolean { 63 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 64 | isNetWorkAvailableM(context) 65 | } else { 66 | isNetWorkAvailableL(context) 67 | } 68 | } 69 | 70 | 71 | // 获取 ConnectivityManager 72 | private fun getManager(context: Context): ConnectivityManager { 73 | return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 74 | } 75 | 76 | // 23以下 判断是否连接 77 | private fun isNetWorkAvailableL(context: Context): Boolean { 78 | val manger = getManager(context) 79 | val info = manger.activeNetworkInfo 80 | return info != null && info.isConnected 81 | } 82 | 83 | // 23以上 判断是否连接 84 | @RequiresApi(Build.VERSION_CODES.M) 85 | private fun isNetWorkAvailableM(context: Context): Boolean { 86 | val connectivityManager = getManager(context) 87 | val networkCapabilities = connectivityManager.activeNetwork 88 | val actNw = 89 | connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false 90 | return when { 91 | // wifi网络 92 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true 93 | // 蜂窝网络 94 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true 95 | // 以太网 96 | actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true 97 | else -> false 98 | } 99 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/MoyaDSL.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya 2 | 3 | import android.content.Context 4 | import com.allens.moya.config.LoggerConfig 5 | import com.allens.moya.config.NetWorkCache 6 | import com.allens.moya.config.NetWorkTimeOut 7 | import com.allens.moya.delegate.LambdaDelegate 8 | import com.allens.moya.enums.LoggerLevel 9 | import com.allens.moya.impl.OnCookieInterceptor 10 | import retrofit2.CallAdapter 11 | import retrofit2.Converter 12 | 13 | /*** 14 | * 此类是 moya 的拓展属性,方便使用dsl 实现接口配置 15 | * 不过因为名称不能和拓展方法相同。所以将参数简化 16 | * 例如 baseUrl --> url 17 | */ 18 | 19 | fun moya(context: Context, block: Moya.Builder.() -> Unit): Moya { 20 | return Moya.Builder().apply { 21 | block() 22 | }.build(context) 23 | } 24 | 25 | 26 | var Moya.Builder.url: String 27 | get() = httpConfig.baseUrl 28 | set(value) { 29 | baseUrl(value) 30 | } 31 | 32 | var Moya.Builder.retry: Boolean 33 | get() = httpConfig.retryOnConnectionFailure 34 | set(value) { 35 | retryOnConnectionFailure(value) 36 | } 37 | 38 | var Moya.Builder.level: LoggerLevel 39 | get() = httpConfig.level 40 | set(value) { 41 | logLevel(value) 42 | } 43 | 44 | var Moya.Builder.debug: Boolean 45 | get() = Moya.debug 46 | set(value) { 47 | debug(value) 48 | } 49 | 50 | // 配置网络超时时间等 51 | var Moya.Builder.time: NetWorkTimeOut.() -> Unit by LambdaDelegate( 52 | NetWorkTimeOut() 53 | ) { netWorkTime, builder -> 54 | builder.connectTimeout(time = netWorkTime.connect) 55 | builder.readTimeout(time = netWorkTime.read) 56 | builder.writeTimeout(time = netWorkTime.write) 57 | } 58 | 59 | // 配置缓存等 60 | var Moya.Builder.cache: NetWorkCache.() -> Unit by LambdaDelegate( 61 | NetWorkCache() 62 | ) { cache, builder -> 63 | builder.cacheNetWorkTimeOut(cache.networkTimeOut) 64 | builder.cacheNoNetWorkTimeOut(cache.noNetworkTimeOut) 65 | builder.cacheSize(cache.size) 66 | builder.cachePath(cache.path) 67 | builder.cacheType(cache.type) 68 | } 69 | 70 | // 配置通用的请求头 71 | var Moya.Builder.head: HashMap.() -> Unit by LambdaDelegate, Moya.Builder>( 72 | HashMap() 73 | ) { map, builder -> 74 | map.forEach { 75 | builder.head(it.key, it.value) 76 | } 77 | } 78 | 79 | // 配置日志 80 | var Moya.Builder.log: LoggerConfig.() -> Unit by LambdaDelegate( 81 | LoggerConfig() 82 | ) { log, builder -> 83 | builder.logLevel(log.level) 84 | log.interceptors?.forEach { 85 | builder.logInterceptor(it) 86 | } 87 | } 88 | 89 | // 配置工厂 90 | var Moya.Builder.adapter: MutableSet.() -> Unit by LambdaDelegate, Moya.Builder>( 91 | mutableSetOf() 92 | ) { set, builder -> 93 | set.forEach { 94 | builder.callAdapterFactory(it) 95 | } 96 | } 97 | 98 | // 配置工厂 99 | var Moya.Builder.converter: MutableSet.() -> Unit by LambdaDelegate, Moya.Builder>( 100 | mutableSetOf() 101 | ) { set, builder -> 102 | set.forEach { 103 | builder.converterFactory(it) 104 | } 105 | } 106 | 107 | // 配置 cookie 108 | var Moya.Builder.cookie: MutableSet.() -> Unit by LambdaDelegate, Moya.Builder>( 109 | mutableSetOf() 110 | ) { set, builder -> 111 | set.forEach { 112 | builder.cookieInterceptor(it) 113 | } 114 | } 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/tools/FileTool.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.tools 2 | 3 | 4 | import com.allens.moya.request.DownLoadRequest 5 | import com.allens.moya.tools.MoyaLogTool 6 | import okhttp3.ResponseBody 7 | import java.io.File 8 | import java.io.RandomAccessFile 9 | import java.nio.channels.FileChannel 10 | import java.text.DecimalFormat 11 | 12 | 13 | object FileTool { 14 | 15 | 16 | internal fun downToFile( 17 | currentLength: Long, 18 | responseBody: ResponseBody, 19 | request: DownLoadRequest, 20 | error: () -> Unit, 21 | success: (String) -> Unit, 22 | progress: (currentProgress: Int, currentSaveLength: Long, fileLength: Long) -> Unit, 23 | stop: () -> Boolean, 24 | afterStopSave :()->Unit 25 | ) { 26 | val filePath = getFilePath(request.path!!, request.name!!) 27 | if (filePath == null) { 28 | error() 29 | return 30 | } 31 | val fileLength = getFileLength(currentLength, responseBody) 32 | val inputStream = responseBody.byteStream() 33 | val accessFile = RandomAccessFile(File(filePath), "rwd") 34 | val channel = accessFile.channel 35 | val mappedBuffer = channel.map( 36 | FileChannel.MapMode.READ_WRITE, 37 | currentLength, 38 | fileLength - currentLength 39 | ) 40 | val buffer = ByteArray(1024 * 4) 41 | var len :Int 42 | var lastProgress = 0 43 | var currentSaveLength = currentLength // 当前的长度 44 | 45 | while (inputStream.read(buffer).also { len = it } != -1) { 46 | if (stop()) { 47 | afterStopSave() 48 | break 49 | } 50 | mappedBuffer.put(buffer, 0, len) 51 | currentSaveLength += len 52 | val currentProgress = (currentSaveLength.toFloat() / fileLength * 100).toInt() // 计算百分比 53 | if (lastProgress != currentProgress) { 54 | lastProgress = currentProgress 55 | progress(currentProgress, currentSaveLength, fileLength) 56 | if (currentSaveLength == fileLength) { 57 | success(filePath) 58 | } 59 | } 60 | } 61 | inputStream.close() 62 | accessFile.close() 63 | channel.close() 64 | } 65 | 66 | //数据总长度 67 | private fun getFileLength( 68 | currentLength: Long, 69 | responseBody: ResponseBody 70 | ) = 71 | if (currentLength == 0L) responseBody.contentLength() else currentLength + responseBody.contentLength() 72 | 73 | 74 | // 获取下载地址 75 | private fun getFilePath(savePath: String, saveName: String): String? { 76 | if (!createFile(savePath)) { 77 | return null 78 | } 79 | return "$savePath/$saveName" 80 | 81 | } 82 | 83 | 84 | // 创建文件夹 85 | private fun createFile(downLoadPath: String): Boolean { 86 | val file = File(downLoadPath) 87 | if (!file.exists()) { 88 | return file.mkdirs() 89 | } 90 | return true 91 | } 92 | 93 | 94 | // 格式化小数 95 | fun bytes2kb(bytes: Long): String { 96 | return bytes.toKB() 97 | } 98 | } 99 | 100 | // 定义GB的计算常量 101 | private const val GB = 1024 * 1024 * 1024 102 | 103 | // 定义MB的计算常量 104 | private const val MB = 1024 * 1024 105 | 106 | // 定义KB的计算常量 107 | private const val KB = 1024 108 | 109 | // 拓展函数格式化 110 | fun Long.toKB(): String { 111 | val format = DecimalFormat("###.0") 112 | return when { 113 | this / GB >= 1 -> { 114 | format.format(this / GB) + "GB" 115 | } 116 | this / MB >= 1 -> { 117 | format.format(this / MB) + "MB" 118 | } 119 | this / KB >= 1 -> { 120 | format.format(this / KB) + "KB" 121 | } 122 | else -> { 123 | "${this}B" 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/proto.tab.keystream: -------------------------------------------------------------------------------- 1 | com/allens/tea/Versionscom/allens/tea/Libscom/allens/tea/Libs$Accompanistcom/allens/tea/Libs$Kotlincom/allens/tea/Libs$Coroutinescom/allens/tea/Libs$AndroidX%com/allens/tea/Libs$AndroidX$Activity$com/allens/tea/Libs$AndroidX$Compose'com/allens/tea/Libs$AndroidX$Navigation!com/allens/tea/Libs$AndroidX$Test%com/allens/tea/Libs$AndroidX$Test$Ext&com/allens/tea/Libs$AndroidX$Lifecyclecom/allens/tea/Depscom/allens/tea/Deps$Companion.kotlin_modulecom/allens/tea/BuildConfigcom/allens/tea/Libs$Squareup$com/allens/tea/Libs$Squareup$OkHttp3com/allens/tea/Libs$Googlecom/allens/tea/Libs$Tencentcom/allens/tea/Libs$Lifecyclecom/allens/tea/Libs$Customcom/allens/tea/Libs$Github -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/constants.tab.keystream: -------------------------------------------------------------------------------- 1 | com/allens/tea/Versionscom/allens/tea/Libscom/allens/tea/Libs$Accompanistcom/allens/tea/Libs$Kotlincom/allens/tea/Libs$Coroutinescom/allens/tea/Libs$AndroidX%com/allens/tea/Libs$AndroidX$Activity$com/allens/tea/Libs$AndroidX$Compose'com/allens/tea/Libs$AndroidX$Navigation!com/allens/tea/Libs$AndroidX$Test%com/allens/tea/Libs$AndroidX$Test$Ext&com/allens/tea/Libs$AndroidX$Lifecyclecom/allens/tea/Depscom/allens/tea/BuildConfigcom/allens/tea/Libs$Squareup$com/allens/tea/Libs$Squareup$OkHttp3com/allens/tea/Libs$Googlecom/allens/tea/Libs$Tencentcom/allens/tea/Libs$Lifecyclecom/allens/tea/Libs$Customcom/allens/tea/Libs$Github -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/subtypes.tab.keystream: -------------------------------------------------------------------------------- 1 | org.gradle.api.Plugin -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/supertypes.tab.keystream: -------------------------------------------------------------------------------- 1 | com.allens.tea.Deps -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/file-to-id.tab.keystream: -------------------------------------------------------------------------------- 1 | :$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt2$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/inputs/source-to-output.tab.keystream: -------------------------------------------------------------------------------- 1 | :$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt2$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/lookups/id-to-file.tab.keystream: -------------------------------------------------------------------------------- 1 |  2 |  -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-attributes.tab.keystream: -------------------------------------------------------------------------------- 1 | com.allens.tea.Versionscom.allens.tea.Libscom.allens.tea.Libs.Accompanistcom.allens.tea.Libs.Kotlincom.allens.tea.Libs.Coroutinescom.allens.tea.Libs.AndroidX%com.allens.tea.Libs.AndroidX.Activity$com.allens.tea.Libs.AndroidX.Compose'com.allens.tea.Libs.AndroidX.Navigation!com.allens.tea.Libs.AndroidX.Test%com.allens.tea.Libs.AndroidX.Test.Ext&com.allens.tea.Libs.AndroidX.Lifecyclecom.allens.tea.Depscom.allens.tea.Deps.Companioncom.allens.tea.BuildConfigcom.allens.tea.Libs.Squareup$com.allens.tea.Libs.Squareup.OkHttp3com.allens.tea.Libs.Googlecom.allens.tea.Libs.Tencentcom.allens.tea.Libs.Lifecyclecom.allens.tea.Libs.Customcom.allens.tea.Libs.Github -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream: -------------------------------------------------------------------------------- 1 | :$PROJECT_DIR$/src/main/java/com/allens/tea/Dependencies.kt2$PROJECT_DIR$/src/main/java/com/allens/tea/Deps.kt -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream: -------------------------------------------------------------------------------- 1 | com.allens.tea.Versionscom.allens.tea.Libscom.allens.tea.Libs.Accompanistcom.allens.tea.Libs.Kotlincom.allens.tea.Libs.Coroutinescom.allens.tea.Libs.AndroidX%com.allens.tea.Libs.AndroidX.Activity$com.allens.tea.Libs.AndroidX.Compose'com.allens.tea.Libs.AndroidX.Navigation!com.allens.tea.Libs.AndroidX.Test%com.allens.tea.Libs.AndroidX.Test.Ext&com.allens.tea.Libs.AndroidX.Lifecyclecom.allens.tea.Depscom.allens.tea.Deps.Companioncom.allens.tea.BuildConfigcom.allens.tea.Libs.Squareup$com.allens.tea.Libs.Squareup.OkHttp3com.allens.tea.Libs.Googlecom.allens.tea.Libs.Tencentcom.allens.tea.Libs.Lifecyclecom.allens.tea.Libs.Customcom.allens.tea.Libs.Github -------------------------------------------------------------------------------- /versionPlugin/build/kotlin/compileKotlin/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream: -------------------------------------------------------------------------------- 1 | com/allens/tea/Versionscom/allens/tea/Libscom/allens/tea/Libs$Accompanistcom/allens/tea/Libs$Kotlincom/allens/tea/Libs$Coroutinescom/allens/tea/Libs$AndroidX%com/allens/tea/Libs$AndroidX$Activity$com/allens/tea/Libs$AndroidX$Compose'com/allens/tea/Libs$AndroidX$Navigation!com/allens/tea/Libs$AndroidX$Test%com/allens/tea/Libs$AndroidX$Test$Ext&com/allens/tea/Libs$AndroidX$Lifecyclecom/allens/tea/Depscom/allens/tea/Deps$Companioncom/allens/tea/BuildConfigcom/allens/tea/Libs$Squareup$com/allens/tea/Libs$Squareup$OkHttp3com/allens/tea/Libs$Googlecom/allens/tea/Libs$Tencentcom/allens/tea/Libs$Lifecyclecom/allens/tea/Libs$Customcom/allens/tea/Libs$Github -------------------------------------------------------------------------------- /moya-coroutines/src/main/kotlin/com/allens/moya_coroutines/request/RequestBasis.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya_coroutines.request 2 | 3 | import androidx.lifecycle.LifecycleOwner 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.lifecycleScope 6 | import androidx.lifecycle.viewModelScope 7 | import com.allens.moya.manager.HttpManager 8 | import com.allens.moya.request.Request 9 | import com.allens.moya.result.* 10 | import com.allens.moya.tools.MoyaLogTool 11 | import com.allens.moya_coroutines.impl.ApiService 12 | import kotlinx.coroutines.* 13 | import okhttp3.ResponseBody 14 | import retrofit2.Response 15 | 16 | //============================================================= 17 | // 公共方法 18 | //============================================================= 19 | internal fun getService(manager: HttpManager): ApiService { 20 | return manager.getService() 21 | } 22 | 23 | internal fun getServiceWithOutLogInterceptor(manager: HttpManager): ApiService { 24 | return manager.getServiceWithOutLogInterceptor() 25 | } 26 | 27 | internal fun Response.string(): String? { 28 | return body()?.string() 29 | } 30 | 31 | suspend inline fun execute( 32 | manager: HttpManager, 33 | crossinline block: suspend () -> String? 34 | ): HttpResult = withContext(Dispatchers.IO) { 35 | decode(manager) { block() } 36 | } 37 | 38 | 39 | inline fun executeDisable( 40 | config: Request.Builder.Config, 41 | manager: HttpManager, 42 | crossinline block: suspend (HttpResult) -> Unit, 43 | crossinline action: suspend () -> String? 44 | ): Disposable { 45 | val job = executeRequest(viewModel = config.viewModel, lifecycleOwner = config.owner) { 46 | val result = decode(manager) { action() } 47 | withContext(Dispatchers.Main) { 48 | block(result) 49 | } 50 | } 51 | return CoroutinesDisposable(job) 52 | } 53 | 54 | inline fun executeDisable( 55 | config: Request.Builder.Config, 56 | manager: HttpManager, 57 | crossinline init: HttpBuilder.() -> Unit, 58 | crossinline action: suspend () -> String? 59 | ): Disposable { 60 | val job = executeRequest(viewModel = config.viewModel, lifecycleOwner = config.owner) { 61 | val result = decode(manager) { action() } 62 | val apply = HttpBuilder().apply(init) 63 | withContext(Dispatchers.Main) { 64 | if (result is HttpResult.Success) { 65 | MoyaLogTool.i("请求成功") 66 | apply.onSuccess(result.data) 67 | } else if (result is HttpResult.Error) { 68 | MoyaLogTool.i("请求失败:${result.throwable.message}") 69 | apply.onError(result.throwable) 70 | } 71 | apply.onComplete() 72 | } 73 | } 74 | return CoroutinesDisposable(job) 75 | } 76 | 77 | inline fun executeUpLoadDisable( 78 | viewModel: ViewModel?, 79 | lifecycle: LifecycleOwner?, 80 | manager: HttpManager, 81 | builder: UpLoadBuilder, 82 | crossinline action: suspend () -> String? 83 | ): Disposable { 84 | val job = executeRequest(viewModel = viewModel, lifecycleOwner = lifecycle) { 85 | val result = decode(manager) { action() } 86 | 87 | withContext(Dispatchers.Main) { 88 | if (result is HttpResult.Success) { 89 | MoyaLogTool.i("上传请求成功") 90 | builder.onSuccess(result.data) 91 | } else if (result is HttpResult.Error) { 92 | MoyaLogTool.i("上传请求失败:${result.throwable.message}") 93 | builder.onError(result.throwable) 94 | } 95 | builder.onComplete() 96 | } 97 | } 98 | return CoroutinesDisposable(job) 99 | } 100 | 101 | 102 | inline fun executeRequest( 103 | viewModel: ViewModel?, 104 | lifecycleOwner: LifecycleOwner?, 105 | start: CoroutineStart = CoroutineStart.DEFAULT, 106 | crossinline block: suspend CoroutineScope.() -> Unit 107 | ): Job = when { 108 | viewModel != null -> viewModel.viewModelScope 109 | lifecycleOwner != null -> lifecycleOwner.lifecycleScope 110 | else -> { 111 | throw Throwable("must bind viewModel or lifecycleOwner please use lifecycle() or viewModel() to bind") 112 | } 113 | }.launch(Dispatchers.IO, start) { 114 | block() 115 | } 116 | 117 | inline fun decode( 118 | manager: HttpManager, 119 | block: () -> String?, 120 | ): HttpResult { 121 | return try { 122 | val name1 = T::class.java.name 123 | val name2 = String::class.java.name 124 | if (name1 == name2) { 125 | HttpResult.Success(block() as T) 126 | } else { 127 | HttpResult.Success(manager.gson.fromJson(block(), T::class.java)) 128 | } 129 | } catch (t: Throwable) { 130 | HttpResult.Error(t) 131 | } 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/livedata/DownLoadStatusLiveData.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.livedata 2 | 3 | import androidx.annotation.MainThread 4 | import androidx.lifecycle.* 5 | import com.allens.moya.manager.DownLoadManagerImpl 6 | import com.allens.moya.request.BasicDownLoadRequest 7 | import com.allens.moya.request.DownLoadRequest 8 | import com.allens.moya.request.Request 9 | import com.allens.moya.request.getKey 10 | import com.allens.moya.result.Disposable 11 | import com.allens.moya.result.DownLoadBuilder 12 | import com.allens.moya.result.DownLoadResult 13 | import com.allens.moya.tools.MoyaLogTool 14 | 15 | typealias DownLoadStatusLiveData = MutableLiveData 16 | 17 | 18 | @MainThread 19 | fun DownLoadStatusLiveData.observerState( 20 | manager: DownLoadManagerImpl, 21 | config: Request.Builder.Config, 22 | request: DownLoadRequest, 23 | init: (DownLoadBuilder.() -> Unit)? = null 24 | ) { 25 | 26 | val result: DownLoadBuilder? = if (init != null) { 27 | DownLoadBuilder().apply(init) 28 | } else { 29 | null 30 | } 31 | val function: (t: DownLoadResult) -> Unit = { status -> 32 | when (status) { 33 | is DownLoadResult.Error -> { 34 | MoyaLogTool.i("下载失败 ${status.throwable.message}") 35 | changeFromError(result, status, request) 36 | } 37 | is DownLoadResult.Success -> { 38 | MoyaLogTool.i("下载成功 保存位置 ${status.data}") 39 | changeFromSuccess(result, status, request) 40 | } 41 | is DownLoadResult.Prepare -> { 42 | MoyaLogTool.i("准备下载请求") 43 | changeFromPrepare(result, request) 44 | } 45 | is DownLoadResult.Progress -> { 46 | MoyaLogTool.i("下载进度 ${status.progress}") 47 | changeFromProgress(result, status, request) 48 | } 49 | is DownLoadResult.Cancel -> { 50 | MoyaLogTool.i("下载取消") 51 | changeFromCancel(result, request) 52 | } 53 | is DownLoadResult.Pause -> { 54 | MoyaLogTool.i("下载暂停") 55 | changeFromPause(result, request) 56 | } 57 | } 58 | } 59 | val observer = Observer(function) 60 | val lifeCycle = config.owner 61 | when { 62 | lifeCycle != null -> { 63 | //如果传入了 lifecycle 就交给lifecycle控制,缺点是在后台的时候,不会在change变化 64 | observe(lifeCycle, observer) 65 | lifeCycle.lifecycle.addObserver(object : LifecycleEventObserver { 66 | override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { 67 | if (event == Lifecycle.Event.ON_DESTROY) { 68 | manager.observer.remove(request.getKey()) 69 | } 70 | } 71 | }) 72 | } 73 | else -> { 74 | // 如果没有lifecycle 就需要自己在合适的实际 remove observer 75 | // 好处就是可以在后台也刷新。不过没意义。因为一般的刷新进度都是给用户看的。 76 | // 在后台了用户就看不到了 需要用户自行去remove 77 | observeForever(observer) 78 | manager.observer[request.getKey()] = Pair(this, observer) 79 | } 80 | } 81 | } 82 | 83 | private fun changeFromPause( 84 | result: DownLoadBuilder?, 85 | request: DownLoadRequest 86 | ) { 87 | result?.onPause?.invoke(request.getKey()) 88 | request.listener?.onDownLoadPause(request.getKey()) 89 | } 90 | 91 | private fun changeFromCancel( 92 | result: DownLoadBuilder?, 93 | request: DownLoadRequest 94 | ) { 95 | result?.onCancel?.invoke(request.getKey()) 96 | request.listener?.onDownLoadCancel(request.getKey()) 97 | } 98 | 99 | private fun changeFromProgress( 100 | result: DownLoadBuilder?, 101 | status: DownLoadResult.Progress, 102 | request: DownLoadRequest 103 | ) { 104 | result?.onProgress?.invoke(request.getKey(), status.progress) 105 | request.listener?.onDownLoadProgress(request.getKey(), status.progress) 106 | result?.onUpdate?.invoke( 107 | request.getKey(), 108 | status.progress, 109 | status.read, 110 | status.count, 111 | status.done 112 | ) 113 | request.listener?.onUpdate( 114 | request.getKey(), 115 | status.progress, 116 | status.read, 117 | status.count, 118 | status.done 119 | ) 120 | } 121 | 122 | 123 | private fun changeFromPrepare( 124 | result: DownLoadBuilder?, 125 | request: DownLoadRequest 126 | ) { 127 | result?.onPrepare?.invoke(request.getKey()) 128 | request.listener?.onDownLoadPrepare(request.getKey()) 129 | } 130 | 131 | private fun changeFromSuccess( 132 | result: DownLoadBuilder?, 133 | status: DownLoadResult.Success, 134 | request: DownLoadRequest 135 | ) { 136 | result?.onSuccess?.invoke(request.getKey(), status.data) 137 | request.listener?.onDownLoadSuccess( 138 | key = request.getKey(), 139 | path = status.data 140 | ) 141 | } 142 | 143 | private fun changeFromError( 144 | result: DownLoadBuilder?, 145 | status: DownLoadResult.Error, 146 | request: DownLoadRequest 147 | ) { 148 | result?.onError?.invoke(request.getKey(), status.throwable) 149 | request.listener?.onDownLoadError(request.getKey(), status.throwable) 150 | } -------------------------------------------------------------------------------- /moya/src/main/kotlin/com/allens/moya/manager/HttpManager.kt: -------------------------------------------------------------------------------- 1 | package com.allens.moya.manager 2 | 3 | import android.content.Context 4 | import android.os.Environment 5 | import android.os.Handler 6 | import android.os.Looper 7 | import com.allens.moya.interceptor.CacheNetworkInterceptor 8 | import com.allens.moya.config.DefaultConfig 9 | import com.allens.moya.config.MoyaConfig 10 | import com.allens.moya.enums.NetWorkCacheType 11 | import com.allens.moya.interceptor.* 12 | import com.allens.moya.tools.MoyaLogTool 13 | import com.allens.moya.tools.PrefTools 14 | import com.franmontiel.persistentcookiejar.PersistentCookieJar 15 | import com.franmontiel.persistentcookiejar.cache.SetCookieCache 16 | import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor 17 | import com.google.gson.Gson 18 | import okhttp3.Cache 19 | import okhttp3.Interceptor 20 | import okhttp3.OkHttpClient 21 | import retrofit2.Retrofit 22 | import java.io.File 23 | 24 | 25 | class HttpManager { 26 | 27 | 28 | var handler = Handler(Looper.getMainLooper()) 29 | val gson = Gson() 30 | lateinit var retrofit: Retrofit 31 | lateinit var retrofitDownLoad: Retrofit 32 | private lateinit var context: Context 33 | private lateinit var config: MoyaConfig 34 | 35 | fun createManager(config: MoyaConfig, context: Context): HttpManager = apply { 36 | this.config = config 37 | MoyaLogTool.i("httpConfig:$config") 38 | 39 | this.context = context.applicationContext 40 | 41 | // 初始化 MMKV 42 | PrefTools.init(context) 43 | 44 | val interceptor = LogInterceptor.register(config, handler) 45 | 46 | val okHttpBuilder = buildOkHttp(interceptor) 47 | retrofit = createRetrofit(config, okHttpBuilder) 48 | // 下载和网络请求使用不同的retrofit 防止@Steaming 不起作用 49 | okHttpBuilder.interceptors().remove(interceptor) 50 | retrofitDownLoad = createRetrofit(config, okHttpBuilder) 51 | } 52 | 53 | 54 | private fun buildOkHttp(logInterceptor: Interceptor): OkHttpClient.Builder { 55 | val okHttpBuilder = OkHttpClient.Builder() 56 | 57 | val cookieJar = 58 | PersistentCookieJar( 59 | SetCookieCache(), 60 | SharedPrefsCookiePersistor(context) 61 | ) 62 | // 第三方库 管理 cookie 63 | okHttpBuilder.cookieJar(cookieJar) 64 | okHttpBuilder.connectTimeout(config.connectTime, config.connectTimeTimeUnit) 65 | okHttpBuilder.readTimeout(config.readTime, config.readTimeTimeUnit) 66 | okHttpBuilder.writeTimeout(config.writeTime, config.writeTimeTimeUnit) 67 | okHttpBuilder.retryOnConnectionFailure(config.retryOnConnectionFailure) 68 | 69 | 70 | // 动态替换BaseURL 71 | okHttpBuilder.addInterceptor(DynamicBaseUrlInterceptor) 72 | // 动态替换连接超时 73 | okHttpBuilder.addInterceptor(DynamicTimeoutInterceptor) 74 | // 添加日志拦截器 75 | okHttpBuilder.addInterceptor(logInterceptor) 76 | val map = config.heardMap 77 | 78 | // 添加请求头 79 | if (!map.isNullOrEmpty()) { 80 | okHttpBuilder.addInterceptor(HeardInterceptor.register(map)) 81 | } 82 | 83 | // cookie 拦截器 84 | config.cookieSet.forEach { 85 | okHttpBuilder.addInterceptor(ReceivedCookieInterceptor.register(it)) 86 | } 87 | 88 | // cache 缓存 89 | val cacheSize = config.cacheSize // 10 MiB 90 | val cache = Cache( 91 | File( 92 | if (config.cachePath.isEmpty()) { 93 | getBasePath(context) + File.separator + DefaultConfig.DEFAULT_CACHE_PATH 94 | } else { 95 | config.cachePath 96 | } 97 | ), cacheSize.toLong() 98 | ) 99 | 100 | // 添加自定义的拦截器 101 | config.interceptor.forEach { 102 | okHttpBuilder.addInterceptor(it) 103 | } 104 | 105 | // 设置缓存 106 | if (config.cacheNetWorkType != NetWorkCacheType.NONE) { 107 | okHttpBuilder 108 | .addInterceptor(CacheInterceptor(context, config)) 109 | .addNetworkInterceptor(CacheNetworkInterceptor(config)) 110 | .cache(cache) 111 | } 112 | 113 | return okHttpBuilder 114 | } 115 | 116 | private fun createRetrofit(config: MoyaConfig, okHttpBuilder: OkHttpClient.Builder): Retrofit { 117 | val retrofitBuilder = Retrofit.Builder() 118 | val client = retrofitBuilder 119 | .client(okHttpBuilder.build()) 120 | 121 | this.config.callAdapterFactorySet.forEach { 122 | client.addCallAdapterFactory(it) 123 | } 124 | 125 | 126 | this.config.converterFactorySet.forEach { 127 | client.addConverterFactory(it) 128 | } 129 | return client 130 | .baseUrl(config.baseUrl) 131 | .build() 132 | } 133 | 134 | 135 | inline fun getService(): T { 136 | return retrofit.create(T::class.java) 137 | } 138 | 139 | inline fun getServiceWithOutLogInterceptor(): T { 140 | return retrofitDownLoad.create(T::class.java) 141 | } 142 | 143 | 144 | // 获取更路径 145 | private fun getBasePath(context: Context): String { 146 | var p: String = Environment.getExternalStorageState() 147 | val f: File? = context.getExternalFilesDir(null) 148 | if (null != f) { 149 | p = f.absolutePath 150 | } 151 | return p 152 | } 153 | 154 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MOya 2 | 3 | ## 配置 4 | 5 | 使用 Moya.Builder()构造器创建一个moya对象 6 | 7 | ``` 8 | private val moya by lazy { 9 | Moya.Builder() 10 | // base url 11 | .baseUrl("https://www.wanandroid.com") 12 | // 读写连接超时 13 | .connectTimeout(10) 14 | .readTimeout(10) 15 | .writeTimeout(10) 16 | // 缓存配置 17 | .cacheType(CacheType.NONE) 18 | .cachePath("") 19 | .cacheSize(10) 20 | 21 | .cacheNetWorkTimeOut(10) 22 | .cacheNoNetWorkTimeOut(10) 23 | // 日志配置 24 | .logLevel(LoggerLevel.BASIC) 25 | .debug(true) 26 | .logInterceptor(object : OnLogInterceptor { 27 | override fun onLogInterceptorInfo(message: String) { 28 | 29 | } 30 | }) 31 | // 构建工厂配置 32 | // .callAdapterFactory() 33 | // .converterFactory() 34 | // 配置全部请求头 35 | .head("hello", "world") 36 | // 构建moya 37 | .build(this) 38 | } 39 | ``` 40 | 41 | 或者你可以使用 dsl 去创建一个,推荐使用这种方式。更佳清晰 42 | 43 | ``` 44 | private val moya by lazy { 45 | moya(this) { 46 | url = "https://www.wanandroid.com" 47 | retry = true 48 | time = { 49 | connect = 1L 50 | write = 2L 51 | read = 3L 52 | } 53 | cache = { 54 | type = CacheType.NONE 55 | path = "" 56 | size = 10 57 | noNetworkTimeOut = 10 58 | networkTimeOut = 10 59 | } 60 | head = { 61 | put("hello", "world") 62 | } 63 | log = { 64 | level = LoggerLevel.BASIC 65 | interceptors = setOf(object : OnLogInterceptor { 66 | override fun onLogInterceptorInfo(message: String) { 67 | 68 | } 69 | }) 70 | } 71 | 72 | adapter = {} 73 | converter = {} 74 | cookie = {} 75 | } 76 | } 77 | ``` 78 | 79 | ## 请求 80 | 81 | 常规的请求,下面模拟一个Get 请求 82 | 83 | ``` 84 | moya.create() 85 | //一定需要添加一个 lifecycle 或者 viewModel 86 | .lifecycle(this) 87 | .parameter("k", "java") 88 | //这里泛形可以直接使用对象。 89 | .doGet("wxarticle/chapters/json") { 90 | onSuccess = { showRequestDialog(it) } 91 | onError = { showRequestDialog(it.message ?: " is empty ") } 92 | onComplete = { hideLoadDialog() } 93 | } 94 | ``` 95 | 96 | 与协程一起使用 97 | 98 | ``` 99 | viewModel.viewModelScope.launch { 100 | moya.create() 101 | .parameter("username", "moya") 102 | .parameter("password", "123456") 103 | .parameter("repassword", "123456") 104 | .doPost("user/register") 105 | .doComplete { hideLoadDialog() } 106 | .doFailed { showRequestDialog(it.message ?: " is empty ") } 107 | .doSuccess { showRequestDialog(it.toString()) } 108 | } 109 | ``` 110 | 111 | ### 下载 112 | 113 | 使用`DownLoadRequest.Builder()` 创建一个下载对象即可。 114 | 115 | > 注意 116 | 117 | 如果在下载中绑定了 lifeCycle 则当绑定的Activity 或者Fragment 进入后天 下载状态不会执行。当进入前台以后才会将状态刷新。 118 | 如果没有绑定。则需要在合适的地方。例如Activity 的 onDestroy 方法中执行 `CoroutinesDownLoadManager.removeObserver()` 119 | 120 | ``` 121 | addButton("下载 - 查看logcat") { 122 | // 支持断点下载 暂停等操作。 123 | 124 | val request = DownLoadRequest.Builder() 125 | .tag("tag-1") 126 | .name("1.jpg") 127 | .path(cacheDir.path + File.separator + "download") 128 | .build("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1714860920,1362844517&fm=26&gp=0.jpg") 129 | 130 | // 暂停操作执行 131 | // moya.create().doPauseDownLoad(request) 132 | 133 | // 取消操作执行 134 | // moya.create().doCancelDownLoad(request) 135 | 136 | viewModel.viewModelScope.launch { 137 | moya.create() 138 | // 如果传入了 lifecycle 就交给lifecycle控制,缺点是在后台的时候,不会在change变化 139 | // 如果没有绑定lifecycle 则需要自己去执行下面的代码去removeObserver 140 | // CoroutinesDownLoadManager.removeObserver() 141 | 142 | //根于实际情况处理 143 | .lifecycle(this@MainActivity) 144 | 145 | .doDownLoad( 146 | request 147 | ) { 148 | onSuccess = { tag, path -> 149 | Log.i(TAG, "onSuccess:$tag path:$path") 150 | } 151 | onCancel = { 152 | Log.i(TAG, "onCancel:$it") 153 | } 154 | onPause = { 155 | Log.i(TAG, "onPrepare:$it") 156 | } 157 | onProgress = { tag, progress -> 158 | Log.i(TAG, "onProgress:$tag progress:$progress") 159 | } 160 | onUpdate = { tag: String, 161 | progress: Int, 162 | read: Long, 163 | count: Long, 164 | done: Boolean -> 165 | Log.i( 166 | TAG, 167 | "onUpdate:tag:$tag progress:$progress,read:$read,count:$count,done:$done" 168 | ) 169 | } 170 | onError = { tag, throwable -> 171 | Log.i(TAG, "onError tag:$tag info:${throwable.message}") 172 | } 173 | onPrepare = { 174 | Log.i(TAG, "onPrepare tag:$it ") 175 | } 176 | } 177 | } 178 | } 179 | ``` 180 | 181 | ### 上传 182 | 183 | 184 | ``` 185 | addButton("上传") { 186 | viewModel.viewModelScope.launch { 187 | moya.create() 188 | .file( 189 | "file", 190 | File(cacheDir.path + File.separator + "download" + File.separator + "1.jpg") 191 | ) 192 | .baseUrl("https://imgkr.com/") 193 | .heard("Referer", "https://imgkr.com/") 194 | .doUpLoad("api/v2/files/upload") { 195 | onSuccess = { Log.i(TAG, "onSuccess :$it ") } 196 | onError = { Log.i(TAG, "onError :$it ") } 197 | onProgress = { progress: Int, current: Long, length: Long -> 198 | Log.i( 199 | TAG, 200 | "onProgress progress:$progress,current:$current,length:$length " 201 | ) 202 | } 203 | } 204 | } 205 | 206 | } 207 | ``` 208 | 209 | ## 下载使用 210 | 211 | Add it in your root build.gradle at the end of repositories: 212 | 213 | ``` 214 | allprojects { 215 | repositories { 216 | ... 217 | maven { url 'https://www.jitpack.io' } 218 | } 219 | } 220 | ``` 221 | Step 2. Add the dependency 222 | ``` 223 | dependencies { 224 | implementation 'com.github.JiangHaiYang01:Moya:Tag' 225 | } 226 | ``` 227 | 228 | [![](https://www.jitpack.io/v/JiangHaiYang01/Moya.svg)](https://www.jitpack.io/#JiangHaiYang01/Moya) --------------------------------------------------------------------------------