├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml └── misc.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── freddy │ │ └── shine │ │ └── java │ │ └── example │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── freddy │ │ │ └── shine │ │ │ └── java │ │ │ └── example │ │ │ ├── BaseRepository.java │ │ │ ├── CustomParser1.java │ │ │ ├── CustomParser2.java │ │ │ ├── CustomResponseModel1.java │ │ │ ├── CustomResponseModel2.java │ │ │ ├── History.java │ │ │ ├── Journalism.java │ │ │ ├── MainActivity.java │ │ │ └── TestRepository.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── freddy │ └── shine │ └── java │ └── example │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── shine-java ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── freddy │ └── shine │ └── java │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml └── java │ └── com │ └── freddy │ └── shine │ └── java │ ├── AbstractRequestManager.java │ ├── RequestManagerFactory.java │ ├── ShineKit.java │ ├── cipher │ ├── AbstractCipher.java │ ├── DefaultCipher.java │ └── ICipher.java │ ├── config │ ├── NetworkConfig.java │ ├── RequestMethod.java │ ├── RequestOptions.java │ ├── ShineConfig.java │ └── ShineOptions.java │ ├── exception │ └── RequestException.java │ ├── interf │ └── IRequest.java │ ├── listener │ ├── IResponseListener.java │ ├── OnResponseListener.java │ └── ResponseListAdapter.java │ ├── model │ ├── DefaultResponseModel.java │ └── IResponseModel.java │ ├── parser │ ├── AbstractParser.java │ ├── DefaultParser.java │ └── IParser.java │ ├── retrofit │ ├── api │ │ └── IApiService.java │ ├── converter │ │ └── StringConverterFactory.java │ ├── interceptor │ │ ├── OkHttpBaseInterceptor.java │ │ ├── OkHttpLoggingInterceptor.java │ │ ├── OkHttpRequestEncryptInterceptor.java │ │ ├── OkHttpRequestHeaderInterceptor.java │ │ └── OkHttpResponseDecryptInterceptor.java │ └── manager │ │ ├── RetrofitManager.java │ │ └── RetrofitRequestManager.java │ └── utils │ ├── ParameterizedTypeImpl.java │ ├── RxExecutor.java │ ├── ShineLog.java │ └── TypeUtil.java └── test └── java └── com └── freddy └── shine └── java └── ExampleUnitTest.java /.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 | ======= 16 | # Built application files 17 | *.apk 18 | *.aar 19 | *.ap_ 20 | *.aab 21 | 22 | # Files for the ART/Dalvik VM 23 | *.dex 24 | 25 | # Java class files 26 | *.class 27 | 28 | # Generated files 29 | bin/ 30 | gen/ 31 | out/ 32 | # Uncomment the following line in case you need and you don't have the release build type files in your app 33 | # release/ 34 | 35 | # Gradle files 36 | .gradle/ 37 | build/ 38 | 39 | # Local configuration file (sdk path, etc) 40 | local.properties 41 | 42 | # Proguard folder generated by Eclipse 43 | proguard/ 44 | 45 | # Log Files 46 | *.log 47 | 48 | # Android Studio Navigation editor temp files 49 | .navigation/ 50 | 51 | # Android Studio captures folder 52 | captures/ 53 | 54 | # IntelliJ 55 | .idea/workspace.xml 56 | .idea/tasks.xml 57 | .idea/gradle.xml 58 | .idea/assetWizardSettings.xml 59 | .idea/dictionaries 60 | .idea/libraries 61 | # Android Studio 3 in .gitignore file. 62 | .idea/caches 63 | .idea/modules.xml 64 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 65 | .idea/navEditor.xml 66 | 67 | # Keystore files 68 | # Uncomment the following lines if you do not want to check your keystore files in. 69 | #*.jks 70 | #*.keystore 71 | 72 | # External native build folder generated in Android Studio 2.2 and later 73 | .cxx/ 74 | 75 | # Google Services (e.g. APIs or Firebase) 76 | # google-services.json 77 | 78 | # Freeline 79 | freeline.py 80 | freeline/ 81 | freeline_project_description.json 82 | 83 | # fastlane 84 | fastlane/report.xml 85 | fastlane/Preview.html 86 | fastlane/screenshots 87 | fastlane/test_output 88 | fastlane/readme.md 89 | 90 | # Version control 91 | vcs.xml 92 | 93 | # lint 94 | lint/intermediates/ 95 | lint/generated/ 96 | lint/outputs/ 97 | lint/tmp/ 98 | # lint/reports/ 99 | 100 | shine-java/scripts/ -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Shine-Java -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shine-Java 2 | 基于Retrofit+RxJava实现的Java网络请求库封装,支持GET/POST/PUT/DELETE请求、动态BaseUrl、请求头、请求/响应日志、自定义加解密器等。同时,支持自定义Parser(数据解析器),用于解决不同返回数据Model。 3 | 4 | ## 文章链接 5 | [Shine——更简单的Android网络请求库封装](https://juejin.cn/user/2084329776750989/posts) 6 | 7 | ## 使用方式 8 | 代码示例为**Kotlin**版本,Java版本请自行修改。 9 | 1. 添加依赖 10 | * **Java** 11 | `implementation "io.github.freddychen:shine-java:$lastest_version"` 12 | * **Kotlin** 13 | `implementation "io.github.freddychen:shine-kotlin:$lastest_version"` 14 | 15 | *Note:最新版本可在[maven central shine](https://search.maven.org/artifact/io.github.freddychen/shine-java)中找到。* 16 | 17 | 2. 初始化 18 | 使用**Shine**前进行初始化,建议放到**Application#onCreate()**。 19 | ``` 20 | val options = ShineOptions.Builder() 21 | .setLogEnable(true) 22 | .setLogTag("FreddyChen") 23 | .setBaseUrl("https://api.oick.cn/") 24 | .setParserCls(CustomParser1::class) 25 | .build() 26 | ShineKit.init(options) 27 | ``` 28 | 当然,初始化不是强制的,**ShineOptions**会有对应的默认值,默认值可参考*参数及API说明#ShineOptions* 29 | 30 | 3. 使用 31 | ``` 32 | suspend fun fetchCatList(): ArrayList { 33 | val options = RequestOptions.Builder() 34 | .setRequestMethod(RequestMethod.GET) 35 | .setBaseUrl("https://cat-fact.herokuapp.com/") 36 | .setFunction("facts/random?amount=2&animal_type=cat") 37 | .build() 38 | 39 | val type = object : TypeToken>() {}.type 40 | return ShineKit.getRequestManager().request( 41 | options = options, 42 | type = type, 43 | parserCls = CustomParser1::class 44 | ) 45 | } 46 | ``` 47 | 当然,**Type**及**Parser**参数传递我们可以利用**Kotlin**特性封装一个通用的请求方法,这些大家根据自己的业务情况来选择就好,下面提供一个示例: 48 | ``` 49 | /** 50 | * 异步请求 51 | */ 52 | suspend inline fun request( 53 | requestMethod: RequestMethod, 54 | baseUrl: String = "https://api.oick.cn/", 55 | function: String, 56 | headers: ArrayMap? = null, 57 | params: ArrayMap? = null, 58 | contentType: String = NetworkConfig.DEFAULT_CONTENT_TYPE, 59 | parserCls: KClass = CustomParser1::class, 60 | cipherCls: KClass? = null 61 | ): T { 62 | val optionsBuilder = RequestOptions.Builder() 63 | .setRequestMethod(requestMethod) 64 | .setBaseUrl(baseUrl) 65 | .setFunction(function) 66 | .setContentType(contentType) 67 | 68 | if (!headers.isNullOrEmpty()) { 69 | optionsBuilder.setHeaders(headers) 70 | } 71 | 72 | if (!params.isNullOrEmpty()) { 73 | optionsBuilder.setParams(params) 74 | } 75 | 76 | return ShineKit.getRequestManager() 77 | .request(optionsBuilder.build(), object : TypeToken() {}.type, parserCls, cipherCls) 78 | } 79 | ```` 80 | 这样的话,上面的请求可以简化为: 81 | ``` 82 | suspend fun fetchCatList(): ArrayList { 83 | return request( 84 | requestMethod = RequestMethod.GET, 85 | baseUrl = "https://cat-fact.herokuapp.com/", 86 | function = "facts/random?amount=2&animal_type=cat", 87 | ) 88 | } 89 | ``` 90 | 91 | 4. 示例 92 | * 获取历史列表数据 93 | | 服务器域名 | 接口地址 | 参数 | 返回数据结构 | 备注 | 94 | | -- | -- | -- | -- | -- | 95 | | https://api.oick.cn/ | lishi/api.php | / | code、day、result | / | 96 | 97 | 例: 98 | ``` 99 | { 100 | "code":"1", 101 | "day":"01/ 17", 102 | "result":[ 103 | { 104 | "date":"395年01月17日", 105 | "title":"罗马帝国分裂为西罗马帝国和东罗马帝国" 106 | } 107 | ] 108 | } 109 | ``` 110 | 调用方式: 111 | ``` 112 | suspend fun fetchHistoryList(): ArrayList { 113 | return request( 114 | requestMethod = RequestMethod.POST, 115 | function = "lishi/api.php", 116 | ) 117 | } 118 | ``` 119 | 120 | * 获取新闻列表数据 121 | | 服务器域名 | 接口地址 | 参数 | 返回数据结构 | 备注 | 122 | | -- | -- | -- | -- | -- | 123 | | https://is.snssdk.com/ | api/news/feed/v51/ | / | message、data | / | 124 | 125 | 例: 126 | ``` 127 | { 128 | "message":"success", 129 | "data":[ 130 | { 131 | "content":"test" 132 | } 133 | ] 134 | } 135 | ``` 136 | 调用方式: 137 | ``` 138 | suspend fun fetchJournalismList(): ArrayList { 139 | return request( 140 | requestMethod = RequestMethod.GET, 141 | baseUrl = "https://is.snssdk.com/", 142 | function = "api/news/feed/v51/", 143 | parserCls = CustomParser2::class, 144 | ) 145 | } 146 | 147 | ``` 148 | *Note:如有业务需求使用同步请求方式,只需要把`request()`方法改成`syncRequest()`方法即可*。 149 | 150 | ## 版本记录 151 | 152 | | 版本号 | 修改时间 | 版本说明 | 153 | | -- | -- | -- | 154 | | 0.0.7 | 2022.01.16 | 首次提交 | 155 | 156 | ## 免费开放的Api 157 | 提供两个免费开放Api平台给大家,方便测试: 158 | * [红花会 / 免费的api接口](https://gitee.com/safflower_club/free_api_interface#https://gitee.com/link?target=https%3A%2F%2Fwww.free-api.com%2Fdoc%2F533) 159 | * [public-apis](https://github.com/public-apis/public-apis) 160 | 161 | # License 162 | 163 | 164 | Copyright 2022, chenshichao 165 | 166 | Licensed under the Apache License, Version 2.0 (the "License"); 167 | you may not use this file except in compliance with the License. 168 | You may obtain a copy of the License at 169 | 170 | http://www.apache.org/licenses/LICENSE-2.0 171 | 172 | Unless required by applicable law or agreed to in writing, software 173 | distributed under the License is distributed on an "AS IS" BASIS, 174 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 175 | See the License for the specific language governing permissions and 176 | limitations under the License. 177 | 178 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdk 31 7 | 8 | defaultConfig { 9 | applicationId "com.freddy.shine.java.example" 10 | minSdk 19 11 | targetSdk 31 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | multiDexEnabled true 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_1_8 27 | targetCompatibility JavaVersion.VERSION_1_8 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation 'androidx.appcompat:appcompat:1.3.1' 33 | implementation 'com.google.android.material:material:1.4.0' 34 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 35 | testImplementation 'junit:junit:4.13.2' 36 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 38 | 39 | def gson_version = '2.8.9' 40 | implementation "com.google.code.gson:gson:$gson_version" 41 | 42 | def multidex_version = "2.0.1" 43 | implementation "androidx.multidex:multidex:$multidex_version" 44 | 45 | implementation project(':shine-java') 46 | // def shine_java_version = '0.0.5' 47 | // implementation "io.github.freddychen:shine-java:$shine_java_version" 48 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /app/src/androidTest/java/com/freddy/shine/java/example/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.freddy.shine.java.example", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/BaseRepository.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.ShineKit; 4 | import com.freddy.shine.java.cipher.ICipher; 5 | import com.freddy.shine.java.config.NetworkConfig; 6 | import com.freddy.shine.java.config.RequestMethod; 7 | import com.freddy.shine.java.config.RequestOptions; 8 | import com.freddy.shine.java.exception.RequestException; 9 | import com.freddy.shine.java.listener.OnResponseListener; 10 | import com.freddy.shine.java.parser.IParser; 11 | import com.freddy.shine.java.utils.TypeUtil; 12 | import java.lang.reflect.Type; 13 | import java.util.List; 14 | 15 | /** 16 | * @author: FreddyChen 17 | * @date : 2022/01/15 00:57 18 | * @email : freddychencsc@gmail.com 19 | */ 20 | public abstract class BaseRepository { 21 | 22 | /** 23 | * 异步请求 24 | * @param options 25 | * @param type 26 | * @param parserCls 27 | * @param cipherCls 28 | * @param listener 29 | * @param 30 | */ 31 | protected void request(RequestOptions options, Type type, Class parserCls, Class cipherCls, OnResponseListener listener) { 32 | ShineKit.getInstance().getRequestManager().request( 33 | options, 34 | type, 35 | parserCls, 36 | cipherCls, 37 | listener 38 | ); 39 | } 40 | 41 | /** 42 | * 同步请求 43 | * @param options 44 | * @param type 45 | * @param parserCls 46 | * @param cipherCls 47 | * @param 48 | * @return 49 | * @throws RequestException 50 | */ 51 | protected T syncRequest(RequestOptions options, Type type, Class parserCls, Class cipherCls) throws RequestException { 52 | return ShineKit.getInstance().getRequestManager().syncRequest( 53 | options, 54 | type, 55 | parserCls, 56 | cipherCls 57 | ); 58 | } 59 | 60 | protected RequestOptions.Builder getDefaultRequestOptionsBuilder(RequestMethod requestMethod, String function) { 61 | return new RequestOptions.Builder() 62 | .setRequestMethod(requestMethod) 63 | .setBaseUrl("https://api.oick.cn/") 64 | .setFunction(function) 65 | .setContentType(NetworkConfig.DEFAULT_CONTENT_TYPE); 66 | } 67 | 68 | protected Type getType(Class clazz) { 69 | return TypeUtil.getType(clazz, clazz); 70 | } 71 | 72 | protected Type getListType(Class clazz) { 73 | return TypeUtil.getType(List.class, clazz); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/CustomParser1.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.exception.RequestException; 4 | import com.freddy.shine.java.model.DefaultResponseModel; 5 | import com.freddy.shine.java.parser.AbstractParser; 6 | import com.freddy.shine.java.utils.ShineLog; 7 | import com.google.gson.reflect.TypeToken; 8 | 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * @author: FreddyChen 13 | * @date : 2022/01/15 00:48 14 | * @email : freddychencsc@gmail.com 15 | */ 16 | public class CustomParser1 extends AbstractParser { 17 | 18 | private static final String TAG = "CustomParser1"; 19 | 20 | @Override 21 | public T parse(String url, String data, Type type) throws RequestException { 22 | ShineLog.i(TAG + "#parse()\ndata = " + data + "\ntype = " + type); 23 | String errMsg = null; 24 | CustomResponseModel1 responseModel = null; 25 | try { 26 | Type responseType = new TypeToken>() { 27 | }.getType(); 28 | responseModel = gson.fromJson(data, responseType); 29 | if (!responseModel.isSuccessful()) { 30 | errMsg = "responseModel is failure"; 31 | } else { 32 | return gson.fromJson(gson.toJson(responseModel.getResult()), type); 33 | } 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | errMsg = e.getMessage(); 37 | } 38 | 39 | RequestException exception = new RequestException(); 40 | exception.setType(RequestException.Type.NATIVE); 41 | exception.setUrl(url); 42 | exception.setStatusCode(200); 43 | exception.setErrMsg(TAG + "#parse() failure\nerrMsg = " + errMsg + "\ntype = " + type + "\nresponseModel = " + responseModel + "\ndata = " + data); 44 | if (responseModel != null) { 45 | Integer errCode = null; 46 | try { 47 | errCode = Integer.parseInt(responseModel.getCode()); 48 | } catch (NumberFormatException e) { 49 | e.printStackTrace(); 50 | } 51 | if (errCode != null) { 52 | exception.setErrCode(errCode); 53 | } 54 | } 55 | throw exception; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/CustomParser2.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.exception.RequestException; 4 | import com.freddy.shine.java.parser.AbstractParser; 5 | import com.freddy.shine.java.utils.ShineLog; 6 | import com.google.gson.reflect.TypeToken; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | /** 11 | * @author: FreddyChen 12 | * @date : 2022/01/15 00:48 13 | * @email : freddychencsc@gmail.com 14 | */ 15 | public class CustomParser2 extends AbstractParser { 16 | 17 | private static final String TAG = "CustomParser1"; 18 | 19 | @Override 20 | public T parse(String url, String data, Type type) throws RequestException { 21 | ShineLog.i(TAG + "#parse()\ndata = " + data + "\ntype = " + type); 22 | String errMsg = null; 23 | CustomResponseModel2 responseModel = null; 24 | try { 25 | Type responseType = new TypeToken>() { 26 | }.getType(); 27 | responseModel = gson.fromJson(data, responseType); 28 | if (!responseModel.isSuccessful()) { 29 | errMsg = "responseModel is failure"; 30 | } else { 31 | return gson.fromJson(gson.toJson(responseModel.getData()), type); 32 | } 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | errMsg = e.getMessage(); 36 | } 37 | 38 | RequestException exception = new RequestException(); 39 | exception.setType(RequestException.Type.NATIVE); 40 | exception.setUrl(url); 41 | exception.setStatusCode(200); 42 | exception.setErrMsg(TAG + "#parse() failure\nerrMsg = " + errMsg + "\ntype = " + type + "\nresponseModel = " + responseModel + "\ndata = " + data); 43 | 44 | throw exception; 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/CustomResponseModel1.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.model.IResponseModel; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * @author: FreddyChen 8 | * @date : 2022/01/15 00:50 9 | * @email : freddychencsc@gmail.com 10 | */ 11 | public class CustomResponseModel1 implements IResponseModel { 12 | 13 | @SerializedName("code") 14 | private String code; 15 | @SerializedName("day") 16 | private String day; 17 | @SerializedName("result") 18 | private T result; 19 | 20 | public String getCode() { 21 | return code; 22 | } 23 | 24 | public String getDay() { 25 | return day; 26 | } 27 | 28 | public T getResult() { 29 | return result; 30 | } 31 | 32 | @Override 33 | public boolean isSuccessful() { 34 | return "1".equals(this.code); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "CustomResponseModel1{" + 40 | "code='" + code + '\'' + 41 | ", day='" + day + '\'' + 42 | ", result=" + result + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/CustomResponseModel2.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.model.IResponseModel; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * @author: FreddyChen 8 | * @date : 2022/01/15 00:50 9 | * @email : freddychencsc@gmail.com 10 | */ 11 | public class CustomResponseModel2 implements IResponseModel { 12 | 13 | @SerializedName("message") 14 | private String message; 15 | @SerializedName("data") 16 | private T data; 17 | 18 | public String getMessage() { 19 | return message; 20 | } 21 | 22 | public T getData() { 23 | return data; 24 | } 25 | 26 | @Override 27 | public boolean isSuccessful() { 28 | return "success".equals(this.message); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "CustomResponseModel2{" + 34 | "message='" + message + '\'' + 35 | ", data=" + data + 36 | '}'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/History.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * @author: FreddyChen 7 | * @date : 2022/01/17 16:33 8 | * @email : freddychencsc@gmail.com 9 | */ 10 | public class History { 11 | 12 | @SerializedName("date") 13 | private String date; 14 | @SerializedName("title") 15 | private String title; 16 | 17 | public String getDate() { 18 | return date; 19 | } 20 | 21 | public String getTitle() { 22 | return title; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "History{" + 28 | "date='" + date + '\'' + 29 | ", title='" + title + '\'' + 30 | '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/Journalism.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * @author: FreddyChen 7 | * @date : 2022/01/17 16:32 8 | * @email : freddychencsc@gmail.com 9 | */ 10 | public class Journalism { 11 | 12 | @SerializedName("code") 13 | private String code; 14 | @SerializedName("content") 15 | private String content; 16 | 17 | public String getCode() { 18 | return code; 19 | } 20 | 21 | public String getContent() { 22 | return content; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "Journalism{" + 28 | "code='" + code + '\'' + 29 | ", content='" + content + '\'' + 30 | '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.View; 8 | 9 | import com.freddy.shine.java.ShineKit; 10 | import com.freddy.shine.java.config.ShineOptions; 11 | import com.freddy.shine.java.exception.RequestException; 12 | import com.freddy.shine.java.listener.ResponseListAdapter; 13 | 14 | import java.util.List; 15 | 16 | public class MainActivity extends AppCompatActivity { 17 | 18 | private static final String TAG = "MainActivity"; 19 | private View btn1, btn2; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | ShineOptions options = new ShineOptions.Builder() 26 | .setLogEnable(true) 27 | .setLogTag("FreddyChen") 28 | .setBaseUrl("https://api.oick.cn/") 29 | .setParserCls(CustomParser1.class) 30 | .build(); 31 | ShineKit.getInstance().init(options); 32 | TestRepository repository = new TestRepository(); 33 | 34 | btn1 = findViewById(R.id.btn_1); 35 | btn2 = findViewById(R.id.btn_2); 36 | 37 | btn1.setOnClickListener(v -> { 38 | Log.i(TAG, "异步请求开始"); 39 | repository.fetchHistoryList(new ResponseListAdapter>() { 40 | 41 | @Override 42 | public void onStart() { 43 | Log.i(TAG, "fetchHistoryList#onStart()"); 44 | } 45 | 46 | @Override 47 | public void onSuccessful(List result) { 48 | Log.i(TAG, "fetchHistoryList#onSuccessful() historyList = " + result); 49 | } 50 | 51 | @Override 52 | public void onFailure(RequestException exception) { 53 | Log.i(TAG, "fetchHistoryList#onFailure() exception = " + exception); 54 | } 55 | 56 | @Override 57 | public void onFinish() { 58 | Log.i(TAG, "fetchHistoryList#onFinish()"); 59 | } 60 | }); 61 | Log.i(TAG, "异步请求结束"); 62 | }); 63 | 64 | btn2.setOnClickListener(v -> new Thread(() -> { 65 | Log.i(TAG, "同步请求开始"); 66 | try { 67 | List journalismList = repository.fetchJournalismList(); 68 | Log.i(TAG, "journalismList = " + journalismList); 69 | } catch (RequestException exception) { 70 | exception.printStackTrace(); 71 | } 72 | Log.i(TAG, "同步请求结束"); 73 | }).start()); 74 | } 75 | } -------------------------------------------------------------------------------- /app/src/main/java/com/freddy/shine/java/example/TestRepository.java: -------------------------------------------------------------------------------- 1 | package com.freddy.shine.java.example; 2 | 3 | import com.freddy.shine.java.config.RequestMethod; 4 | import com.freddy.shine.java.config.RequestOptions; 5 | import com.freddy.shine.java.exception.RequestException; 6 | import com.freddy.shine.java.listener.OnResponseListener; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author: FreddyChen 12 | * @date : 2022/01/15 00:56 13 | * @email : freddychencsc@gmail.com 14 | */ 15 | public class TestRepository extends BaseRepository { 16 | 17 | /** 18 | * 获取历史列表数据 19 | * 异步请求 20 | * 21 | * @param listener 22 | */ 23 | public void fetchHistoryList(OnResponseListener> listener) { 24 | RequestOptions.Builder builder = getDefaultRequestOptionsBuilder(RequestMethod.GET, "lishi/api.php"); 25 | request(builder.build(), getListType(History.class), CustomParser1.class, null, listener); 26 | } 27 | 28 | /** 29 | * 获取新闻列表数据 30 | * 同步请求 31 | * 32 | * @return 33 | * @throws RequestException 34 | */ 35 | public List fetchJournalismList() throws RequestException { 36 | RequestOptions options = new RequestOptions.Builder() 37 | .setRequestMethod(RequestMethod.GET) 38 | .setBaseUrl("http://is.snssdk.com/") 39 | .setFunction("api/news/feed/v51/") 40 | .build(); 41 | return syncRequest(options, getListType(Journalism.class), CustomParser2.class, null); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |