Showing preview only (831K chars total). Download the full file or copy to clipboard to get everything.
Repository: liujingxing/rxhttp
Branch: master
Commit: abf9696ae585
Files: 230
Total size: 760.0 KB
Directory structure:
gitextract_l14p6_sk/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── example/
│ │ └── httpsender/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── httpsender/
│ │ │ ├── AppHolder.java
│ │ │ ├── DownloadMultiAdapter.java
│ │ │ ├── ExceptionHelper.java
│ │ │ ├── LoggingEventListener.kt
│ │ │ ├── MainActivity.java
│ │ │ ├── MyViewModel.kt
│ │ │ ├── OnError.java
│ │ │ ├── Presenter.kt
│ │ │ ├── RxHttpManager.java
│ │ │ ├── Tip.java
│ │ │ ├── ToolBarActivity.java
│ │ │ ├── adapter/
│ │ │ │ └── FragmentPageAdapter.java
│ │ │ ├── entity/
│ │ │ │ ├── Article.java
│ │ │ │ ├── DownloadTask.java
│ │ │ │ ├── ErrorInfo.java
│ │ │ │ ├── Location.java
│ │ │ │ ├── Name.java
│ │ │ │ ├── NewsDataXml.java
│ │ │ │ ├── NewsXml.java
│ │ │ │ ├── PageList.java
│ │ │ │ ├── Response.java
│ │ │ │ ├── Url.kt
│ │ │ │ └── User.java
│ │ │ ├── fragment/
│ │ │ │ ├── AwaitFragment.kt
│ │ │ │ ├── BaseFragment.kt
│ │ │ │ ├── FlowFragment.kt
│ │ │ │ ├── MultiDownloadFragment.java
│ │ │ │ └── RxJavaFragment.kt
│ │ │ ├── interceptor/
│ │ │ │ ├── RedirectInterceptor.java
│ │ │ │ └── TokenInterceptor.java
│ │ │ ├── kt/
│ │ │ │ ├── Activity.kt
│ │ │ │ ├── KotlinExtensions.kt
│ │ │ │ └── Uri.kt
│ │ │ ├── param/
│ │ │ │ ├── GetEncryptParam.java
│ │ │ │ ├── PostEncryptFormParam.java
│ │ │ │ ├── PostEncryptJsonParam.kt
│ │ │ │ └── PostEncryptJsonParam1.java
│ │ │ ├── parser/
│ │ │ │ ├── Android10DownloadFactory.kt
│ │ │ │ ├── ResponseParser.kt
│ │ │ │ └── java/
│ │ │ │ ├── DoubleTypeParser.java
│ │ │ │ └── ResponseParser.java
│ │ │ ├── utils/
│ │ │ │ └── Preferences.java
│ │ │ ├── view/
│ │ │ │ └── ScaleTransitionPagerTitleView.java
│ │ │ └── vm/
│ │ │ ├── MultiTaskAwaitDownloader.kt
│ │ │ ├── MultiTaskDownloader.kt
│ │ │ └── MultiTaskFlowDownloader.kt
│ │ └── res/
│ │ ├── drawable/
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24/
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ ├── await_fragment.xml
│ │ │ ├── download_multi_adapter.xml
│ │ │ ├── flow_fragment.xml
│ │ │ ├── main_activity.xml
│ │ │ ├── multi_download_fragment.xml
│ │ │ ├── rxjava_fragment.xml
│ │ │ └── toolbar_activity.xml
│ │ ├── menu/
│ │ │ └── download.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values/
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ ├── styles.xml
│ │ │ └── themes.xml
│ │ └── xml/
│ │ └── network_config.xml
│ └── test/
│ └── java/
│ ├── com/
│ │ └── rxhttp/
│ │ └── compiler/
│ │ ├── AbstractTestSymbolProcessor.kt
│ │ ├── KspProcessorTest.kt
│ │ ├── TestParser1.kt
│ │ └── TestParser2.kt
│ └── com.example.httpsender/
│ └── AsyncTest.java
├── build.gradle
├── gradle/
│ ├── libs.versions.toml
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── jitpack.yml
├── maven.gradle
├── maven_dependency.md
├── rxhttp/
│ ├── build.gradle
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── rxhttp/
│ │ │ ├── AwaitTransform.kt
│ │ │ ├── CallFactoryExt.kt
│ │ │ ├── Platform.java
│ │ │ ├── RxHttpPlugins.java
│ │ │ └── wrapper/
│ │ │ ├── CallFactory.kt
│ │ │ ├── OkHttpCompat.java
│ │ │ ├── cache/
│ │ │ │ ├── CacheManager.java
│ │ │ │ ├── CacheMode.java
│ │ │ │ ├── CacheStrategy.java
│ │ │ │ ├── HeadersVary.java
│ │ │ │ └── InternalCache.java
│ │ │ ├── callback/
│ │ │ │ ├── Consumer.java
│ │ │ │ ├── Function.java
│ │ │ │ ├── IConverter.java
│ │ │ │ ├── JsonConverter.java
│ │ │ │ ├── OutputStreamFactory.kt
│ │ │ │ ├── ProgressCallback.java
│ │ │ │ └── ProgressCallbackHelper.kt
│ │ │ ├── converter/
│ │ │ │ └── GsonConverter.java
│ │ │ ├── cookie/
│ │ │ │ ├── CookieStore.java
│ │ │ │ └── ICookieJar.java
│ │ │ ├── coroutines/
│ │ │ │ ├── Await.kt
│ │ │ │ ├── CallAwait.kt
│ │ │ │ └── CallFlow.kt
│ │ │ ├── entity/
│ │ │ │ ├── DownloadOffSize.java
│ │ │ │ ├── EmptyResponseBody.java
│ │ │ │ ├── ExpandOutputStream.java
│ │ │ │ ├── FileRequestBody.java
│ │ │ │ ├── KeyValuePair.java
│ │ │ │ ├── OkResponse.java
│ │ │ │ ├── ParameterizedTypeImpl.java
│ │ │ │ ├── Progress.java
│ │ │ │ ├── UpFile.java
│ │ │ │ └── UriRequestBody.java
│ │ │ ├── exception/
│ │ │ │ ├── CacheReadFailedException.java
│ │ │ │ ├── HttpStatusCodeException.java
│ │ │ │ ├── ParseException.java
│ │ │ │ └── ProxyException.java
│ │ │ ├── intercept/
│ │ │ │ ├── CacheInterceptor.kt
│ │ │ │ ├── LogInterceptor.kt
│ │ │ │ └── RangeInterceptor.java
│ │ │ ├── param/
│ │ │ │ ├── AbstractBodyParam.java
│ │ │ │ ├── AbstractParam.java
│ │ │ │ ├── BodyParam.kt
│ │ │ │ ├── FormParam.java
│ │ │ │ ├── ICache.java
│ │ │ │ ├── IHeaders.java
│ │ │ │ ├── IParam.java
│ │ │ │ ├── IPart.java
│ │ │ │ ├── IRequest.java
│ │ │ │ ├── JsonArrayParam.java
│ │ │ │ ├── JsonParam.java
│ │ │ │ ├── Method.java
│ │ │ │ ├── NoBodyParam.java
│ │ │ │ └── Param.java
│ │ │ ├── parse/
│ │ │ │ ├── OkResponseParser.java
│ │ │ │ ├── Parser.java
│ │ │ │ ├── SmartParser.java
│ │ │ │ ├── StreamParser.kt
│ │ │ │ └── TypeParser.java
│ │ │ ├── progress/
│ │ │ │ └── ProgressRequestBody.java
│ │ │ ├── ssl/
│ │ │ │ └── HttpsUtils.java
│ │ │ └── utils/
│ │ │ ├── BuildUtil.java
│ │ │ ├── CacheUtil.java
│ │ │ ├── Converter.java
│ │ │ ├── Converter.kt
│ │ │ ├── GsonUtil.java
│ │ │ ├── JSONStringer.java
│ │ │ ├── Json.kt
│ │ │ ├── LogTime.java
│ │ │ ├── LogUtil.java
│ │ │ ├── PathEncoder.kt
│ │ │ ├── Speeder.kt
│ │ │ ├── TypeUtil.java
│ │ │ ├── Uri.kt
│ │ │ └── Utils.kt
│ │ └── java-templates/
│ │ └── rxhttp/
│ │ └── internal/
│ │ └── RxHttpVersion.kt
│ └── test/
│ └── java/
│ └── rxhttp/
│ └── wrapper/
│ └── entity/
│ └── ParameterizedTypeImplTest.java
├── rxhttp-annotation/
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── rxhttp/
│ └── wrapper/
│ └── annotation/
│ ├── Converter.java
│ ├── DefaultDomain.java
│ ├── Domain.java
│ ├── OkClient.java
│ ├── Param.java
│ └── Parser.java
├── rxhttp-compiler/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── java/
│ │ └── com/
│ │ └── rxhttp/
│ │ └── compiler/
│ │ ├── Constants.kt
│ │ ├── KaptProcessor.kt
│ │ ├── KspProcessor.kt
│ │ ├── RxJavaVersion.kt
│ │ ├── Variables.kt
│ │ ├── common/
│ │ │ ├── KtUtil.kt
│ │ │ ├── ObservableUtil.kt
│ │ │ └── StringUtil.kt
│ │ ├── kapt/
│ │ │ ├── BaseRxHttpGenerator.kt
│ │ │ ├── ClassHelper.kt
│ │ │ ├── ConverterVisitor.kt
│ │ │ ├── DefaultDomainVisitor.kt
│ │ │ ├── DomainVisitor.kt
│ │ │ ├── OkClientVisitor.kt
│ │ │ ├── ParamsVisitor.kt
│ │ │ ├── ParserVisitor.kt
│ │ │ ├── RxHttpExtensions.kt
│ │ │ ├── RxHttpGenerator.kt
│ │ │ ├── RxHttpWrapper.kt
│ │ │ ├── Utils.kt
│ │ │ └── maven/
│ │ │ ├── KaptRxJava2Processor.kt
│ │ │ └── KaptRxJava3Processor.kt
│ │ └── ksp/
│ │ ├── BaseRxHttpGenerator.kt
│ │ ├── ClassHelper.kt
│ │ ├── ConverterVisitor.kt
│ │ ├── DefaultDomainVisitor.kt
│ │ ├── DomainVisitor.kt
│ │ ├── KClassHelper.kt
│ │ ├── Ksp.kt
│ │ ├── OkClientVisitor.kt
│ │ ├── ParamsVisitor.kt
│ │ ├── ParserVisitor.kt
│ │ ├── RxHttpExtensions.kt
│ │ ├── RxHttpGenerator.kt
│ │ └── RxHttpWrapper.kt
│ └── resources/
│ └── META-INF/
│ ├── gradle/
│ │ └── incremental.annotation.processors
│ └── services/
│ ├── com.google.devtools.ksp.processing.SymbolProcessorProvider
│ └── javax.annotation.processing.Processor
├── rxhttp-converter/
│ ├── converter-fastjson/
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── rxhttp/
│ │ └── wrapper/
│ │ └── converter/
│ │ └── FastJsonConverter.java
│ ├── converter-jackson/
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── rxhttp/
│ │ └── wrapper/
│ │ └── converter/
│ │ └── JacksonConverter.java
│ ├── converter-moshi/
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── rxhttp/
│ │ └── wrapper/
│ │ └── converter/
│ │ └── MoshiConverter.java
│ ├── converter-protobuf/
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── rxhttp/
│ │ └── wrapper/
│ │ └── converter/
│ │ └── ProtoConverter.java
│ ├── converter-serialization/
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── rxhttp/
│ │ └── wrapper/
│ │ └── converter/
│ │ └── SerializationConverter.kt
│ └── converter-simplexml/
│ ├── .gitignore
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── rxhttp/
│ └── wrapper/
│ └── converter/
│ └── XmlConverter.java
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa6d3941c2c944e59831640fa0ece60d~tplv-k3u1fbpfcp-watermark.image
================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.ap_
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
# Keystore files
# Uncomment the following line if you do not want to check your keystore files in.
#*.jks
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# Google Services (e.g. APIs or Firebase)
google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
.idea/codeStyles/Project.xml
.idea/misc.xml
.idea/modules.xml
.idea/runConfigurations.xml
.idea/vcs.xml
.idea
gradlew.bat
gradlew
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# RxHttp
English | [中文文档](https://github.com/liujingxing/rxhttp/blob/master/README_zh.md)
[](https://jitpack.io/#liujingxing/rxhttp)
# [(RxHttp 3.0 更新指南,升级必看)](https://github.com/liujingxing/rxhttp/wiki/RxHttp-3.0-%E6%9B%B4%E6%96%B0%E6%8C%87%E5%8D%97%EF%BC%8C%E5%8D%87%E7%BA%A7%E5%BF%85%E7%9C%8B)
# 使用RxHttp的知名App
<img src="https://pp.myapp.com/ma_icon/0/icon_54221929_1770021797/256" width="100" height="100"/> <img src="https://github.com/user-attachments/assets/1d263296-19b8-4e06-a19f-b656b0dcf4dc" width="100" height="100"/>
抖音旗下***汽水音乐***(app v18.1.0 设置/关于汽水音乐/开源软件声明 可查)
<!--https://uinotes-img.oss-cn-shanghai.aliyuncs.com/logo/origin-webp/321899153012164010.webp-->
# A type-safe HTTP client for Android. Written based on OkHttp

<table>
<tr>
<th align="center">Await</th>
<th align="center">Flow</th>
<th align="center">RxJava<br>(Kotlin)</th>
<th align="center">RxJava<br>(Java)</th>
</tr>
<tr>
<td>
```java
//await return User
//tryAwait return User?
val user = RxHttp.get("/server/..")
.add("key", "value")
.toAwait<User>()
.await()
//or awaitResult return kotlin.Result<T>
RxHttp.get("/server/..")
.add("key", "value")
.toAwait<User>()
.awaitResult {
//Success
}.onFailure {
//Failure
}
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toFlow<User>()
.catch {
//Failure
}.collect {
//Success
}
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toObservable<User>()
.subscribe({
//Success
}, {
//Failure
})
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toObservable(User.class)
.subscribe(user - > {
//Success
}, throwable -> {
//Failure
})
```
</td>
</tr>
</table>
## 1、Feature
- Support kotlin coroutines, RxJava2, RxJava3
- Support Gson, Xml, ProtoBuf, FastJson and other third-party data parsing tools
- Supports automatic closure of requests in FragmentActivity, Fragment, View, ViewModel, and any class
- Support global encryption and decryption, add common parameters and headers, network cache, all support a request set up separately
## 2、usage
1、Adding dependencies and configurations
### Required
<details>
<summary>1、Add jitpack to your build.gradle</summary>
```java
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
```
</details>
<details>
<summary>2、Java 8 or higher</summary>
```java
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
```
</details>
<details open>
<summary>3、Add RxHttp dependency</summary>
```kotlin
plugins {
// kapt/ksp choose one
// id 'kotlin-kapt'
id 'com.google.devtools.ksp' version '2.3.4'
}
dependencies {
def rxhttp_version = '3.5.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "com.github.liujingxing.rxhttp:rxhttp:$rxhttp_version"
// ksp/kapt/annotationProcessor choose one
ksp "com.github.liujingxing.rxhttp:rxhttp-compiler:$rxhttp_version"
}
```
</details>
### Optional
### 1、Converter
```kotlin
implementation "com.github.liujingxing.rxhttp:converter-serialization:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-fastjson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-jackson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-moshi:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-protobuf:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-simplexml:$rxhttp_version"
```
### 2、RxJava
<details open>
<summary>RxHttp + RxJava3</summary>
```java
implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava3:2.2.2' //RxJava3, Automatic close request
```
</details>
<details>
<summary>RxHttp + RxJava2</summary>
```java
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava2:2.2.2' //RxJava2, Automatic close request
```
</details>
<details open>
<summary>ksp passes the RxJava version</summary>
```java
ksp {
arg("rxhttp_rxjava", "3.1.6")
}
```
</details>
<details>
<summary>Kapt passes the RxJava version</summary>
```java
kapt {
arguments {
arg("rxhttp_rxjava", "3.1.6")
}
}
```
</details>
<details>
<summary>javaCompileOptions passes the RxJava version</summary>
```java
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
rxhttp_rxjava: '3.1.6',
]
}
}
}
}
```
</details>
### 3、set RxHttp class package name
<details open>
<summary>ksp pass package name</summary>
```java
ksp {
arg("rxhttp_package", "rxhttp.xxx")
}
```
<details>
<summary>kapt pass package name</summary>
```java
kapt {
arguments {
arg("rxhttp_package", "rxhttp.xxx")
}
}
```
</details>
<details>
<summary>javaCompileOptions pass package name</summary>
```java
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
rxhttp_package: 'rxhttp.xxx'
]
}
}
}
}
```
</details>
**Finally, rebuild the project, which is necessary**
2、Initialize the SDK
This step is optional
```java
RxHttpPlugins.init(OkHttpClient)
.setDebug(boolean)
.setOnParamAssembly(Consumer)
....
```
3、Configuration BaseUrl
This step is optional
```java
public class Url {
//Add the @defaultDomain annotation to BASE_URL
@DefaultDomain
public static BASE_URL = "https://..."
}
```
4、Perform the requested
```java
// java
RxHttp.get("/service/...") //1、You can choose get,postFrom,postJson etc
.addQuery("key", "value") //add query param
.addHeader("headerKey", "headerValue") //add request header
.toObservable(Student.class) //2、Use the toXxx method to determine the return value type, customizable
.subscribe(student -> { //3、Subscribing observer
//Success callback,Default IO thread
}, throwable -> {
//Abnormal callback
});
// kotlin
RxHttp.postForm("/service/...") //post FormBody
.add("key", "value") //add param to body
.addQuery("key1", "value1") //add query param
.addFile("file", File(".../1.png")) //add file to body
.toObservable<Student>()
.subscribe({ student ->
//Default IO thread
}, { throwable ->
})
// kotlin coroutine
val students = RxHttp.postJson("/service/...") //1、post {application/json; charset=utf-8}
.toAwaitList<Student>() //2、Use the toXxx method to determine the return value type, customizable
.await() //3、Get the return value, await is the suspend method
```
## 3、Advanced usage
1、Close the request
```java
//In Rxjava2 , Automatic close request
RxHttp.get("/service/...")
.toObservableString()
.as(RxLife.as(this)) //The Activity destroys and automatically closes the request
.subscribe(s -> {
//Default IO thread
}, throwable -> {
});
//In Rxjava3 , Automatic close request
RxHttp.get("/service/...")
.toObservableString()
.to(RxLife.to(this)) //The Activity destroys and automatically closes the request
.subscribe(s -> {
//Default IO thread
}, throwable -> {
});
//In RxJava2/RxJava3, close the request manually
Disposable disposable = RxHttp.get("/service/...")
.toObservableString()
.subscribe(s -> {
//Default IO thread
}, throwable -> {
});
disposable.dispose(); //Close the request at the appropriate time
```
## 4、ProGuard
If you are using RxHttp v2.2.8 or above the shrinking and obfuscation rules are included automatically.
Otherwise you must manually add the options in [rxhttp.pro](https://github.com/liujingxing/rxhttp/blob/master/rxhttp/src/main/resources/META-INF/proguard/rxhttp.pro).
## 5、Donations
If this project helps you a lot and you want to support the project's development and maintenance of this project, feel free to scan the following QR code for donation. Your donation is highly appreciated. Thank you!

# Licenses
```
Copyright 2019 liujingxing
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
================================================
FILE: README_zh.md
================================================
# RxHttp
[English](https://github.com/liujingxing/rxhttp/blob/master/README.md) | 中文文档
[](https://jitpack.io/#liujingxing/rxhttp)

[](https://github.com/liujingxing/rxhttp/wiki/%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97)
[](https://github.com/liujingxing/rxhttp/wiki/FAQ)
[](https://juejin.cn/user/272334612601559/posts)
<!--[](https://jq.qq.com/?_wv=1027&k=E53Hakvv)-->
# [(RxHttp 3.0 更新指南,升级必看)](https://github.com/liujingxing/rxhttp/wiki/RxHttp-3.0-%E6%9B%B4%E6%96%B0%E6%8C%87%E5%8D%97%EF%BC%8C%E5%8D%87%E7%BA%A7%E5%BF%85%E7%9C%8B)
# 使用RxHttp的知名App
<img src="https://pp.myapp.com/ma_icon/0/icon_54221929_1770021797/256" width="100" height="100"/> <img src="https://github.com/user-attachments/assets/1d263296-19b8-4e06-a19f-b656b0dcf4dc" width="100" height="100"/>
抖音旗下***汽水音乐***(app v18.1.0 设置/关于汽水音乐/开源软件声明 可查)
***加我微信 ljx-studio 拉你进微信群(备注RxHttp)***
# 1、主要优势
***1. 30秒即可上手,学习成本极低***
***2. 史上最优雅的支持 Kotlin 协程***
***3. 史上最优雅的处理多个BaseUrl及动态BaseUrl***
***4. 史上最优雅的对错误统一处理,且不打破Lambda表达式***
***5. 史上最优雅的文件上传/下载/断点下载/进度监听,已适配Android 10***
***6. 支持Gson、Xml、ProtoBuf、FastJson等第三方数据解析工具***
***7. 支持Get、Post、Put、Delete等任意请求方式,可自定义请求方式***
***8. 支持在Activity/Fragment/View/ViewModel/任意类中,自动关闭请求***
***9. 支持全局加解密、添加公共参数及头部、网络缓存,均支持对某个请求单独设置***
# 2、请求三部曲

***代码表示,
[toObservableXxx、toAwaitXxx、toFlowXxx方法介绍点这里](https://github.com/liujingxing/rxhttp/wiki/RxJava%E3%80%81Await%E3%80%81Flow-%E5%AF%B9%E5%BA%94%E7%9A%84-asXxx%E3%80%81toXxx%E3%80%81toFlowXxx%E6%96%B9%E6%B3%95%E4%BB%8B%E7%BB%8D)***
<table>
<tr>
<th align="center">Await</th>
<th align="center">Flow</th>
<th align="center">RxJava<br>(Kotlin)</th>
<th align="center">RxJava<br>(Java)</th>
</tr>
<tr>
<td>
```java
//同步式写法
val user = RxHttp.get("/server/..")
.add("key", "value")
.toAwait<User>()
.await() //tryAwait return User?
//回调式写法
RxHttp.get("/server/..")
.add("key", "value")
.toAwait<User>()
.awaitResult {
//成功回调
}.onFailure {
//异常回调
}
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toFlow<User>()
.catch {
//异常回调
}.collect {
//成功回调
}
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toObservable<User>()
.subscribe({
//成功回调
}, {
//异常回调
})
```
</td>
<td>
```java
RxHttp.get("/server/..")
.add("key", "value")
.toObservable(User.class)
.subscribe(user - > {
//成功回调
}, throwable -> {
//异常回调
})
```
</td>
</tr>
</table>
***RxHttp与Retrofit对比***
| 功能说明 | RxHttp | [Retrofit](https://github.com/square/retrofit) |
| --- | :---: | :---: |
| 版本| v3.2.6| v2.9.0 |
| 状态| 维护中| 维护中 |
| 标准RESTful风格| ✅ | ✅ |
| 学习成本| 低 | 高|
| 扩展性| 高| 高|
| 源码大小| 73k | 75k |
| jar包大小| 210k | 123k |
| RxJava| RxJava ❌<br>RxJava2✅<br>RxJava3✅| RxJava ✅<br>RxJava2✅<br>RxJava3✅|
| Kotlin协程| ✅ | ✅ |
| Flow流| ✅ | ✅ |
| Converter| Gson✅<br> Jackson✅<br> fastJson✅<br> Moshi✅<br> Protobuf✅<br> simplexml✅<br> kotlinx.serialization✅<br> 自定义✅<br> | Gson✅<br> Jackson✅<br> fastJson✅<br> Moshi✅<br> Protobuf✅<br> simplexml✅<br> kotlinx.serialization✅<br> 自定义✅<br> |
| 关闭请求 | 手动✅<br>自动✅<br>批量✅| 手动✅<br>自动✅<br>批量✅ |
| 文件上传/下载/进度监听| ✅ | ❌需再次封装|
| Android 10分区存储| ✅ | ❌需再次封装|
| 公共参数| ✅| ❌需再次封装 |
| 多域名/动态域名| ✅好用 | ✅一般 |
| 日志打印| ✅| ✅ |
| Json数据格式化输出| ✅| ❌需再次封装 |
| 业务code统一判断| ✅ | ❌需再次封装|
| 请求缓存| ✅ | ❌需再次封装|
| 全局加解密| ✅ | ❌需再次封装 |
| 部分字段解密 | ✅ | ❌需再次封装 |
**说明**
也许你有会有疑问,RxHttp源码大小仅比retrofit大6k的情况下,jar包大小为何会大一倍多?功能太多导致的代码臃肿?并不是,而是由kotlin导致的,在RxHttp内部,为了支持`Await/Flow`,运用了大量的kotlin内联方法及扩展方法,这些方法在编译为字节码后,都会相对较大,其中[AwaitTransform.kt](https://github.com/liujingxing/rxhttp/blob/master/rxhttp/src/main/java/rxhttp/AwaitTransform.kt)、[CallFactoryToAwait.kt](https://github.com/liujingxing/rxhttp/blob/master/rxhttp/src/main/java/rxhttp/CallFactoryToAwait.kt)、[CallFactoryToFlow.kt](https://github.com/liujingxing/rxhttp/blob/master/rxhttp/src/main/java/rxhttp/CallFactoryToFlow.kt)这3个kotlin文件,编译字节码后,就接近70k
# 3、相关文档
30秒上手教程:[30秒上手新一代Http请求神器RxHttp](https://juejin.im/post/5cfcbbcbe51d455a694f94df)
Flow文档:[RxHttp + Flow 三步搞定任意请求](https://juejin.cn/post/7017604875764629540)
Await文档:[RxHttp ,比Retrofit 更优雅的协程体验](https://juejin.im/post/5e77604fe51d4527066eb81a#heading-2)
RxJava及核心Api介绍:[RxHttp 让你眼前一亮的Http请求框架](https://juejin.im/post/5ded221a518825125d14a1d4)
wiki详细文档:https://github.com/liujingxing/rxhttp/wiki (此文档会持续更新)
## [(RxHttp 3.0 更新指南,升级必看)](https://github.com/liujingxing/rxhttp/wiki/RxHttp-3.0-%E6%9B%B4%E6%96%B0%E6%8C%87%E5%8D%97%EF%BC%8C%E5%8D%87%E7%BA%A7%E5%BF%85%E7%9C%8B)
自动关闭请求用到的RxLife类,详情请查看[RxLife库](https://github.com/liujingxing/rxlife)
# 4、上手准备
***1、RxHttp依赖有3种方式,选择其中一种就好,
[ksp、kapt、annotationProcessor 如何选择点击这里](https://github.com/liujingxing/rxhttp/wiki/ksp%E3%80%81kapt%E3%80%81annotationProcessor-%E7%94%A8%E6%B3%95%E5%8F%8A%E5%8C%BA%E5%88%AB)***
***2、asXxx方法内部通过RxJava实现,如需使用,需额外依赖RxJava并告知RxHttp你依赖的Rxjava版本***
***3、RxHttp已适配`OkHttp 3.12.0 - v4.12.0`版本(4.3.0除外), 如需兼容21以下,请依赖`OkHttp 3.12.x`,该版本最低要求 API 9***
***4、[Maven依赖点击这里](https://github.com/liujingxing/rxhttp/blob/master/maven_dependency.md)***
## 4.1、必须
<details open>
<summary>annotationProcessor依赖</summary>
```gradle
//1、项目的build.gradle文件
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
//2、java 8或更高
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
//3、添加依赖
dependencies {
def rxhttp_version = '3.5.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "com.github.liujingxing.rxhttp:rxhttp:$rxhttp_version"
annotationProcessor "com.github.liujingxing.rxhttp:rxhttp-compiler:$rxhttp_version"
}
```
</details>
<details>
<summary>kapt依赖</summary>
```gradle
//1、项目的build.gradle文件
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
//2、java 8或更高
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
//3、添加插件及依赖
plugins {
id 'kotlin-kapt'
}
dependencies {
def rxhttp_version = '3.5.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "com.github.liujingxing.rxhttp:rxhttp:$rxhttp_version"
kapt "com.github.liujingxing.rxhttp:rxhttp-compiler:$rxhttp_version"
}
```
</details>
<details>
<summary>ksp依赖</summary>
```gradle
//1、项目的build.gradle文件
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
//2、java 8或更高,及配置sourceSets
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
//3、添加插件及依赖
plugins {
id 'com.google.devtools.ksp' version '2.3.4'
}
dependencies {
def rxhttp_version = '3.5.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "com.github.liujingxing.rxhttp:rxhttp:$rxhttp_version"
ksp "com.github.liujingxing.rxhttp:rxhttp-compiler:$rxhttp_version"
}
```
</details>
## 4.2、可选
### 4.2.1、配置RxJava
如果你需要结合`toObservableXxx`方法发请求,就需要额外依赖`RxJava`,并且告知`rxhttp`你依赖的`RxJava`版本号
- ***依赖RxJava,RxJava2/RxJava3选其一***
```java
//RxJava3
implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava3:2.2.2' //管理RxJava3生命周期,页面销毁,关闭请求
//RxJava2
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava2:2.2.2' //管理RxJava2生命周期,页面销毁,关闭请求
```
- ***通过ksp/kapt/annotationProcessor,其中一种方式传递RxJava版本号***
<details open>
<summary>通过ksp传递RxJava版本</summary>
```java
ksp {
arg("rxhttp_rxjava", "3.1.6")
}
```
</details>
<details>
<summary>通过kapt传递RxJava版本</summary>
```java
kapt {
arguments {
arg("rxhttp_rxjava", "3.1.6")
}
}
```
</details>
<details>
<summary>通过annotationProcessor传递RxJava版本</summary>
```java
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
//使用asXxx方法时必须,传入你依赖的RxJava版本
rxhttp_rxjava: '3.1.6',
]
}
}
}
}
```
</details>
### 4.2.2、配置Converter
```kotlin
//非必须,根据自己需求选择 RxHttp默认内置了GsonConverter
implementation "com.github.liujingxing.rxhttp:converter-serialization:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-fastjson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-jackson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-moshi:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-protobuf:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-simplexml:$rxhttp_version"
```
### 4.2.3、指定RxHttp相关类的存放目录
如果你有多个module依赖`rxhttp-compiler`(不建议这么做,一般base module依赖就好),则每个module下都会生成`RxHttp`类,且目录相同,在运行或打包时,就会出现RxHttp类冲突的问题,此时就需要你自定义RxHttp的存放目录,也就是RxHttp类的包名,`ksp/kapt/annotationProcessor`选择其中一种方式就好
<details open>
<summary>通过ksp指定RxHttp相关类包名</summary>
```java
ksp {
arg("rxhttp_package", "rxhttp") //指定RxHttp类包名,可随意指定
}
```
</details>
<details>
<summary>通过kapt指定RxHttp相关类包名</summary>
```java
kapt {
arguments {
arg("rxhttp_package", "rxhttp") //指定RxHttp类包名,可随意指定
}
}
```
</details>
<details>
<summary>通过javaCompileOptions指定RxHttp相关类包名</summary>
```java
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
rxhttp_package: 'rxhttp', //指定RxHttp类包名,可随意指定
]
}
}
}
}
```
</details>
最后,***rebuild一下(此步骤是必须的)*** ,就会自动生成RxHttp类
# 5、混淆
- `RxHttp v2.2.8`及以上版本,无需添加任何混淆规则,将你自己的Bean类Keep下就好
- `RxHttp v2.2.8`以下版本,将[RxHttp 混淆规则](https://github.com/liujingxing/rxhttp/wiki/关于混淆),添加到自己项目中,并将你自己的Bean类Keep下
# 6、Demo演示
<img src="https://github.com/liujingxing/rxhttp/blob/master/screen/demo.gif" width = "360" height = "640" />
> 更多功能,请[下载apk](https://github.com/liujingxing/rxhttp/blob/master/screen/app-debug.apk)体验
# 7、Donations
如果它对你帮助很大,并且你很想支持库的后续开发和维护,那么你可以扫下方二维码随意打赏我,就当是请我喝杯咖啡或是啤酒,开源不易,感激不尽

# Licenses
```
Copyright 2019 liujingxing
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
================================================
FILE: app/.gitignore
================================================
#/build
/release
================================================
FILE: app/build.gradle
================================================
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id 'kotlin-kapt'
id 'com.google.devtools.ksp' version libs.versions.ksp
}
android {
namespace 'com.example.httpsender'
compileSdk 35
defaultConfig {
applicationId "com.example.rxhttp"
minSdk 23
targetSdk 35
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
buildFeatures {
buildConfig = true
dataBinding = true
}
lint {
abortOnError false
checkReleaseBuilds false
}
}
ksp {
arg("rxhttp_rxjava", libs.versions.rxjava.get())
// arg("rxhttp_package", "rxhttp")
}
kapt {
arguments {
arg("rxhttp_rxjava", libs.versions.rxjava.get()) //可传入rxjava2、rxjava3或具体版本号,如 3.1.1
// arg("rxhttp_package", "rxhttp") //设置RxHttp相关类的包名,多module依赖时,需要配置不同的包名
}
}
dependencies {
implementation libs.androidx.multidex
implementation libs.androidx.appcompat
implementation libs.androidx.recyclerview
implementation libs.androidx.constraintlayout
implementation libs.github.magicindicator
implementation libs.androidx.fragment.ktx
implementation libs.androidx.lifecycle.runtime.ktx
implementation libs.androidx.lifecycle.livedata.ktx
implementation libs.androidx.lifecycle.viewmodel.ktx
implementation libs.androidx.lifecycle.service
implementation projects.rxhttp
ksp projects.rxhttpCompiler
// kapt projects.rxhttpCompiler
implementation libs.okhttp
testImplementation libs.mockwebserver
// implementation libs.rxhttp
// ksp libs.rxhttp.compiler
// kapt libs.rxhttp.compiler
//管理RxJava及生命周期,Activity/Fragment 销毁,自动关闭未完成的请求
implementation libs.github.rxlife.rxjava3
implementation libs.rxandroid
implementation libs.rxjava
// implementation libs.rxhttp.converter.serialization
// implementation libs.rxhttp.converter.fastjson
// implementation libs.rxhttp.converter.jackson
// implementation libs.rxhttp.converter.moshi
// implementation libs.rxhttp.converter.protobuf
// implementation libs.rxhttp.converter.simplexml
implementation projects.rxhttpConverter.converterSerialization
implementation projects.rxhttpConverter.converterFastjson
implementation projects.rxhttpConverter.converterSimplexml
implementation projects.rxhttpConverter.converterProtobuf
implementation projects.rxhttpConverter.converterMoshi
implementation projects.rxhttpConverter.converterJackson
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
implementation libs.utilcodex
testImplementation libs.kotlin.compile.testing.ksp
testImplementation libs.kotlinpoet
testImplementation libs.kotlinpoet.ksp
testImplementation projects.rxhttpCompiler
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keepclassmembers class com.example.httpsender.entity.** {
<init>(); #R8 full mode下, 默认构造方法不保留
!transient <fields>;
}
# With R8 full mode generic signatures are stripped for classes that are not kept.
-keep,allowobfuscation,allowshrinking class com.example.httpsender.entity.Response
-keep,allowobfuscation,allowshrinking class com.example.httpsender.entity.PageList
#依赖simple-xml后打包失败,需加入以下规则
-dontwarn android.content.res.**
#依赖fastjson后打包失败,需加入以下规则
-dontwarn javax.ws.rs.**
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn com.google.common.collect.ArrayListMultimap
-dontwarn com.google.common.collect.Multimap
-dontwarn java.awt.Color
-dontwarn java.awt.Font
-dontwarn java.awt.Point
-dontwarn java.awt.Rectangle
-dontwarn javax.money.CurrencyUnit
-dontwarn javax.money.Monetary
-dontwarn javax.ws.rs.Consumes
-dontwarn javax.ws.rs.Produces
-dontwarn javax.ws.rs.core.Response
-dontwarn javax.ws.rs.core.StreamingOutput
-dontwarn javax.ws.rs.ext.MessageBodyReader
-dontwarn javax.ws.rs.ext.MessageBodyWriter
-dontwarn javax.ws.rs.ext.Provider
-dontwarn org.glassfish.jersey.internal.spi.AutoDiscoverable
-dontwarn org.javamoney.moneta.Money
-dontwarn org.joda.time.DateTime
-dontwarn org.joda.time.DateTimeZone
-dontwarn org.joda.time.Duration
-dontwarn org.joda.time.Instant
-dontwarn org.joda.time.LocalDate
-dontwarn org.joda.time.LocalDateTime
-dontwarn org.joda.time.LocalTime
-dontwarn org.joda.time.Period
-dontwarn org.joda.time.ReadablePartial
-dontwarn org.joda.time.format.DateTimeFormat
-dontwarn org.joda.time.format.DateTimeFormatter
-dontwarn springfox.documentation.spring.web.json.Json
================================================
FILE: app/src/androidTest/java/com/example/httpsender/ExampleInstrumentedTest.java
================================================
package com.example.httpsender;
import android.content.Context;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import io.reactivex.rxjava3.disposables.Disposable;
import rxhttp.wrapper.param.RxHttp;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
Disposable subscribe = RxHttp.get("https://www.wanandroid.com/article/list/0/json")
.toObservableString()
.subscribe(s -> {
System.out.println(s);
}, throwable -> {
Log.e("LJX", "useAppContext");
});
while (!subscribe.isDisposed()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".AppHolder"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
================================================
FILE: app/src/main/java/com/example/httpsender/AppHolder.java
================================================
package com.example.httpsender;
import android.app.Application;
import android.content.Context;
import androidx.multidex.MultiDex;
/**
* User: ljx
* Date: 2019/3/31
* Time: 09:11
*/
//@HiltAndroidApp
public class AppHolder extends Application {
private static AppHolder instance;
public static AppHolder getInstance() {
return instance;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
RxHttpManager.init(this);
}
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/DownloadMultiAdapter.java
================================================
package com.example.httpsender;
import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.httpsender.DownloadMultiAdapter.MyViewHolder;
import com.example.httpsender.entity.DownloadTask;
import com.example.httpsender.vm.MultiTaskDownloader;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;
/**
* User: ljx
* Date: 2019-06-07
* Time: 11:10
*/
public class DownloadMultiAdapter extends RecyclerView.Adapter<MyViewHolder> {
private OnItemClickListener<DownloadTask> mOnItemClickListener;
private List<DownloadTask> mDownloadTasks;
public DownloadMultiAdapter(List<DownloadTask> downloadTasks) {
mDownloadTasks = downloadTasks;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.download_multi_adapter, viewGroup, false);
return new MyViewHolder(view);
}
@SuppressLint("DefaultLocale")
@Override
public void onBindViewHolder(@NonNull MyViewHolder viewHolder, int i) {
DownloadTask data = mDownloadTasks.get(i);
viewHolder.progressBar.setProgress((int) (data.getProgress()*100));
viewHolder.tvProgress.setText(String.format("%.1f%%", data.getProgress() * 100));
viewHolder.btPause.setOnClickListener(v -> {
mOnItemClickListener.onItemClick(v, data, i);
});
String currentSize = new DecimalFormat("0.0").format(data.getCurrentSize() * 1.0f / 1024 / 1024);
String totalSize = new DecimalFormat("0.0").format(data.getTotalSize() * 1.0f / 1024 / 1024);
viewHolder.tvSize.setText(String.format("%sM/%sM", currentSize, totalSize));
int state = data.getState();
if (state == MultiTaskDownloader.IDLE) {
viewHolder.tvWaiting.setText("未开始");
viewHolder.btPause.setText("开始");
} else if (state == MultiTaskDownloader.WAITING) {
viewHolder.tvWaiting.setText("等待中..");
viewHolder.btPause.setText("取消");
} else if (state == MultiTaskDownloader.DOWNLOADING) {
viewHolder.tvWaiting.setText(getSpeed(data.getSpeed()));
long remainingTime = data.getRemainingTime();
if (remainingTime > 0) {
viewHolder.tvWaiting.append(" 预估还需" + getRemainingTime(remainingTime));
}
viewHolder.btPause.setText("暂停");
} else if (state == MultiTaskDownloader.PAUSED) {
viewHolder.tvWaiting.setText("已暂停");
viewHolder.btPause.setText("继续下载");
} else if (state == MultiTaskDownloader.COMPLETED) {
viewHolder.tvWaiting.setText("已完成");
viewHolder.btPause.setText("已完成");
} else if (state == MultiTaskDownloader.FAIL) {
viewHolder.tvWaiting.setText("下载失败");
viewHolder.btPause.setText("重新下载");
} else if (state == MultiTaskDownloader.CANCEL) {
viewHolder.tvWaiting.setText("已取消");
viewHolder.btPause.setText("继续下载");
}
}
private String getSpeed(long speed) {
float kb = speed * 1.0f / 1024;
if (kb > 1000) {
return String.format(Locale.getDefault(), "%.2fMB/s", kb / 1024);
} else {
return ((int) kb) + "KB/s";
}
}
private String getRemainingTime(long time) {
if (time < 300) {
return time + "秒";
} else {
long minute = time / 60;
if (time % 60 > 0) minute++;
return minute + "分";
}
}
@Override
public int getItemCount() {
return mDownloadTasks.size();
}
@Override
public long getItemId(int position) {
return mDownloadTasks.get(position).hashCode();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
ProgressBar progressBar;
TextView tvProgress;
TextView tvSize;
Button btPause;
TextView tvWaiting;
MyViewHolder(@NonNull View itemView) {
super(itemView);
tvWaiting = itemView.findViewById(R.id.tv_waiting);
tvProgress = itemView.findViewById(R.id.tv_progress);
tvSize = itemView.findViewById(R.id.tv_size);
progressBar = itemView.findViewById(R.id.progress_bar);
btPause = itemView.findViewById(R.id.bt_pause);
}
}
public void setOnItemClickListener(OnItemClickListener<DownloadTask> onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public interface OnItemClickListener<T> {
void onItemClick(View view, T data, int position);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/ExceptionHelper.java
================================================
package com.example.httpsender;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* 异常处理帮助类
* User: ljx
* Date: 2019/04/29
* Time: 11:15
*/
public class ExceptionHelper {
@SuppressWarnings("deprecation")
public static boolean isNetworkConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
}
}
return false;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/LoggingEventListener.kt
================================================
package com.example.httpsender
import android.util.Log
import okhttp3.Call
import okhttp3.Connection
import okhttp3.EventListener
import okhttp3.Handshake
import okhttp3.HttpUrl
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.concurrent.TimeUnit
/**
* User: ljx
* Date: 2022/4/22
* Time: 16:05
*/
class LoggingEventListener : EventListener() {
private var startNs: Long = 0
override fun callStart(call: Call) {
startNs = System.nanoTime()
logWithTime("callStart: ${call.request()}")
}
override fun proxySelectStart(call: Call, url: HttpUrl) {
logWithTime("proxySelectStart: $url")
}
override fun proxySelectEnd(call: Call, url: HttpUrl, proxies: List<Proxy>) {
logWithTime("proxySelectEnd: $proxies")
}
override fun dnsStart(call: Call, domainName: String) {
logWithTime("dnsStart: $domainName")
}
override fun dnsEnd(call: Call, domainName: String, inetAddressList: List<InetAddress>) {
logWithTime("dnsEnd: $inetAddressList")
}
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) {
logWithTime("connectStart: $inetSocketAddress $proxy")
}
override fun secureConnectStart(call: Call) {
logWithTime("secureConnectStart")
}
override fun secureConnectEnd(call: Call, handshake: Handshake?) {
logWithTime("secureConnectEnd: $handshake")
}
override fun connectEnd(
call: Call,
inetSocketAddress: InetSocketAddress,
proxy: Proxy,
protocol: Protocol?
) {
logWithTime("connectEnd: $protocol")
}
override fun connectFailed(
call: Call,
inetSocketAddress: InetSocketAddress,
proxy: Proxy,
protocol: Protocol?,
ioe: IOException
) {
logWithTime("connectFailed: $protocol $ioe")
}
override fun connectionAcquired(call: Call, connection: Connection) {
logWithTime("connectionAcquired: $connection")
}
override fun connectionReleased(call: Call, connection: Connection) {
logWithTime("connectionReleased")
}
override fun requestHeadersStart(call: Call) {
logWithTime("requestHeadersStart")
}
override fun requestHeadersEnd(call: Call, request: Request) {
logWithTime("requestHeadersEnd")
}
override fun requestBodyStart(call: Call) {
logWithTime("requestBodyStart")
}
override fun requestBodyEnd(call: Call, byteCount: Long) {
logWithTime("requestBodyEnd: byteCount=$byteCount")
}
override fun requestFailed(call: Call, ioe: IOException) {
logWithTime("requestFailed: $ioe")
}
override fun responseHeadersStart(call: Call) {
logWithTime("responseHeadersStart")
}
override fun responseHeadersEnd(call: Call, response: Response) {
logWithTime("responseHeadersEnd: $response")
}
override fun responseBodyStart(call: Call) {
logWithTime("responseBodyStart")
}
override fun responseBodyEnd(call: Call, byteCount: Long) {
logWithTime("responseBodyEnd: byteCount=$byteCount")
}
override fun responseFailed(call: Call, ioe: IOException) {
logWithTime("responseFailed: $ioe")
}
override fun callEnd(call: Call) {
logWithTime("callEnd")
}
override fun callFailed(call: Call, ioe: IOException) {
logWithTime("callFailed: $ioe")
}
override fun canceled(call: Call) {
logWithTime("canceled")
}
override fun satisfactionFailure(call: Call, response: Response) {
logWithTime("satisfactionFailure: $response")
}
override fun cacheHit(call: Call, response: Response) {
logWithTime("cacheHit: $response")
}
override fun cacheMiss(call: Call) {
logWithTime("cacheMiss")
}
override fun cacheConditionalHit(call: Call, cachedResponse: Response) {
logWithTime("cacheConditionalHit: $cachedResponse")
}
private fun logWithTime(message: String) {
val timeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs)
Log.e("LJX", "[$timeMs ms] $message")
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/MainActivity.java
================================================
package com.example.httpsender;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import com.example.httpsender.adapter.FragmentPageAdapter;
import com.example.httpsender.databinding.MainActivityBinding;
import com.example.httpsender.fragment.AwaitFragment;
import com.example.httpsender.fragment.FlowFragment;
import com.example.httpsender.fragment.MultiDownloadFragment;
import com.example.httpsender.fragment.RxJavaFragment;
import com.example.httpsender.view.ScaleTransitionPagerTitleView;
import net.lucode.hackware.magicindicator.MagicIndicator;
import net.lucode.hackware.magicindicator.ViewPagerHelper;
import net.lucode.hackware.magicindicator.buildins.UIUtil;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.SimplePagerTitleView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private MainActivityBinding mBinding;
private final List<String> mDataList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
mBinding = DataBindingUtil.setContentView(this, R.layout.main_activity);
ViewCompat.setOnApplyWindowInsetsListener(mBinding.getRoot(), new OnApplyWindowInsetsListener() {
@NonNull
@Override
public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
mBinding.magicIndicator.setPadding(0, systemBars.top, 0, 0);
LayoutParams layoutParams = mBinding.magicIndicator.getLayoutParams();
layoutParams.height = (int) (getResources().getDisplayMetrics().density * 50 + systemBars.top);
mBinding.magicIndicator.setLayoutParams(layoutParams);
return insets;
}
});
mBinding.viewPager.setOffscreenPageLimit(4);
mDataList.add("RxJava");
mDataList.add("Await");
mDataList.add("Flow");
mDataList.add("Multi Download");
List<Fragment> fragments = new ArrayList<>();
fragments.add(new RxJavaFragment());
fragments.add(new AwaitFragment());
fragments.add(new FlowFragment());
fragments.add(new MultiDownloadFragment());
mBinding.viewPager.setAdapter(new FragmentPageAdapter(getSupportFragmentManager(), fragments, mDataList));
initMagicIndicator();
}
public void initMagicIndicator() {
MagicIndicator magicIndicator = mBinding.magicIndicator;
CommonNavigator commonNavigator = new CommonNavigator(this);
commonNavigator.setAdapter(new CommonNavigatorAdapter() {
@Override
public int getCount() {
return mDataList == null ? 0 : mDataList.size();
}
@Override
public IPagerTitleView getTitleView(Context context, final int index) {
SimplePagerTitleView simplePagerTitleView = new ScaleTransitionPagerTitleView(context);
simplePagerTitleView.setPadding(dp2px(5), 0, 0, 0);
simplePagerTitleView.setText(mDataList.get(index));
simplePagerTitleView.setTextSize(18);
simplePagerTitleView.setNormalColor(Color.parseColor("#c8e6c9"));
simplePagerTitleView.setSelectedColor(Color.WHITE);
simplePagerTitleView.setOnClickListener(v -> mBinding.viewPager.setCurrentItem(index));
return simplePagerTitleView;
}
@Override
public IPagerIndicator getIndicator(Context context) {
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
indicator.setLineHeight(UIUtil.dip2px(context, 3));
indicator.setLineWidth(UIUtil.dip2px(context, 30));
indicator.setRoundRadius(UIUtil.dip2px(context, 3));
indicator.setStartInterpolator(new AccelerateInterpolator());
indicator.setYOffset(dp2px(3));
indicator.setEndInterpolator(new DecelerateInterpolator(2.0f));
indicator.setColors(Color.WHITE);
return indicator;
}
});
magicIndicator.setNavigator(commonNavigator);
ViewPagerHelper.bind(magicIndicator, mBinding.viewPager);
}
private int dp2px(double dpValue) {
float density = getResources().getDisplayMetrics().density;
return (int) (dpValue * density + 0.5);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/MyViewModel.kt
================================================
package com.example.httpsender
import android.app.Application
import android.util.Log
import androidx.lifecycle.viewModelScope
import com.example.httpsender.entity.Article
import com.example.httpsender.entity.PageList
import com.rxjava.rxlife.ScopeViewModel
import com.rxjava.rxlife.lifeOnMain
import io.reactivex.rxjava3.core.Observable
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import rxhttp.awaitResult
import rxhttp.retry
import rxhttp.timeout
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toAwaitResponse
import java.util.concurrent.TimeUnit
/**
* User: ljx
* Date: 2019-05-31
* Time: 21:50
*/
class MyViewModel(application: Application) : ScopeViewModel(application) {
fun startInterval() {
Observable.interval(1, 1, TimeUnit.SECONDS)
.lifeOnMain(this)
.subscribe { Log.e("LJX", "MyViewModel aLong=$it") }
}
fun testRetry() = viewModelScope.launch {
RxHttp.get("/article/list/0/json")
.toAwaitResponse<PageList<Article>>()
.timeout(100)
.retry(2, 1000) {
it is TimeoutCancellationException
}
.awaitResult {
Log.e("LJX", "pageList=$it")
}
.onFailure {
Log.e("LJX", "it=$it")
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/OnError.java
================================================
package com.example.httpsender;
import com.example.httpsender.entity.ErrorInfo;
import io.reactivex.rxjava3.functions.Consumer;
/**
* RxJava 错误回调 ,加入网络异常处理
* User: ljx
* Date: 2019/04/29
* Time: 11:15
*/
public interface OnError extends Consumer<Throwable> {
@Override
default void accept(Throwable throwable) throws Exception {
onError(new ErrorInfo(throwable));
}
void onError(ErrorInfo error) throws Exception;
}
================================================
FILE: app/src/main/java/com/example/httpsender/Presenter.kt
================================================
package com.example.httpsender
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import com.example.httpsender.entity.Article
import com.example.httpsender.entity.PageList
import com.rxjava.rxlife.BaseScope
import com.rxjava.rxlife.life
import io.reactivex.rxjava3.core.Observable
import kotlinx.coroutines.*
import rxhttp.*
import rxhttp.wrapper.cache.CacheMode
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toAwaitResponse
import java.util.concurrent.TimeUnit
/**
* User: ljx
* Date: 2019-05-26
* Time: 15:20
*/
class Presenter(owner: LifecycleOwner) : BaseScope(owner) {
fun test() {
Observable.interval(1, 1, TimeUnit.SECONDS)
.life(this) //这里的this 为Scope接口对象
.subscribe { Log.e("LJX", "accept aLong=$it") }
}
fun testRetry() {
val coroutineScope: CoroutineScope =
CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
coroutineScope.launch {
RxHttp.postForm("/article/query/0/json")
.add("k", "性能优化")
.setCacheMode(CacheMode.ONLY_NETWORK)
.toAwaitResponse<PageList<Article>>()
.delay(100)
.startDelay(100)
.onErrorReturnItem(PageList())
.timeout(1000)
.retry(2, 1000) {
it is TimeoutCancellationException
}
.awaitResult {
Log.e("RxHttp", "onNext = $it")
}.onFailure {
Log.e("RxHttp", "onError = $it")
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/RxHttpManager.java
================================================
package com.example.httpsender;
import android.app.Application;
import java.io.File;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import rxhttp.RxHttpPlugins;
import rxhttp.wrapper.annotation.Converter;
import rxhttp.wrapper.annotation.OkClient;
import rxhttp.wrapper.callback.IConverter;
import rxhttp.wrapper.converter.FastJsonConverter;
import rxhttp.wrapper.converter.XmlConverter;
import rxhttp.wrapper.cookie.CookieStore;
import rxhttp.wrapper.param.Method;
import rxhttp.wrapper.ssl.HttpsUtils;
import rxhttp.wrapper.ssl.HttpsUtils.SSLParams;
/**
* 本类所有配置都是非必须的,根据自己需求选择就好
* User: ljx
* Date: 2019-11-26
* Time: 20:44
*/
public class RxHttpManager {
@Converter(name = "XmlConverter") //非必须
public static IConverter xmlConverter = XmlConverter.create();
@Converter(name = "FastJsonConverter") //非必须
public static IConverter fastJsonConverter = FastJsonConverter.create();
@OkClient(name = "SimpleClient", className = "Simple") //非必须
public static OkHttpClient simpleClient = new OkHttpClient.Builder().build();
public static void init(Application context) {
File file = new File(context.getExternalCacheDir(), "RxHttpCookie");
SSLParams sslParams = HttpsUtils.getSslSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(new CookieStore(file))
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) //添加信任证书
.hostnameVerifier((hostname, session) -> true) //忽略host验证
// .followRedirects(false) //禁制OkHttp的重定向操作,我们自己处理重定向
// .addInterceptor(new RedirectInterceptor())
// .addInterceptor(new TokenInterceptor())
.build();
//设置缓存策略,非必须
// File cacheFile = new File(context.getExternalCacheDir(), "RxHttpCache");
//RxHttp初始化,非必须
RxHttpPlugins.init(client) //自定义OkHttpClient对象
.setDebug(BuildConfig.DEBUG, false, 2) //调试模式/分段打印/json数据缩进空间
// .setCache(cacheFile, 1000 * 100, CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE)
// .setExcludeCacheKeys("time") //设置一些key,不参与cacheKey的组拼
// .setResultDecoder(s -> s) //设置数据解密/解码器,非必须
// .setConverter(FastJsonConverter.create()) //设置全局的转换器,非必须
.setOnParamAssembly(p -> { //设置公共参数,非必须
//1、可根据不同请求添加不同参数,每次发送请求前都会被回调
//2、如果希望部分请求不回调这里,发请求前调用RxHttp#setAssemblyEnabled(false)即可
Method method = p.getMethod();
if (method.isGet()) {
p.add("method", "get");
} else if (method.isPost()) { //Post请求
p.add("method", "post");
}
p.add("versionName", "1.0.0")//添加公共参数
.add("time", System.currentTimeMillis())
.addHeader("deviceType", "android"); //添加公共请求头
});
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/Tip.java
================================================
package com.example.httpsender;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
/**
* 可在任意线程执行本类方法
* User: ljx
* Date: 2017/3/8
* Time: 10:31
*/
public class Tip {
private static Handler mHandler = new Handler(Looper.getMainLooper());
private static Toast mToast;
public static void show(int msgResId) {
show(msgResId, false);
}
public static void show(int msgResId, boolean timeLong) {
show(AppHolder.getInstance().getString(msgResId), timeLong);
}
public static void show(CharSequence msg) {
show(msg, false);
}
public static void show(final CharSequence msg, final boolean timeLong) {
runOnUiThread(() -> {
if (mToast != null) {
mToast.cancel();
}
int duration = timeLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
mToast = Toast.makeText(AppHolder.getInstance(), msg, duration);
mToast.show();
});
}
private static void runOnUiThread(Runnable runnable) {
if (Looper.getMainLooper() == Looper.myLooper()) {
runnable.run();
} else {
mHandler.post(runnable);
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/ToolBarActivity.java
================================================
package com.example.httpsender;
import android.os.Build;
import android.view.MenuItem;
import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
/**
* 需要ToolBar的activity都必须继承本类
*/
public abstract class ToolBarActivity extends AppCompatActivity {
protected Toolbar toolbar;
protected ActionBar actionBar;
private ViewGroup mContainer;
public <T extends ViewDataBinding> T bindingInflate(@LayoutRes int layoutResID) {
initView();
return DataBindingUtil.inflate(getLayoutInflater(), layoutResID, mContainer, true);
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
initView();
getLayoutInflater().inflate(layoutResID, mContainer, true);
}
private void initView() {
super.setContentView(R.layout.toolbar_activity);
mContainer = findViewById(R.id.container);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == android.R.id.home) {
boolean popSuccess = getSupportFragmentManager().popBackStackImmediate();
if (popSuccess) return true;
finish();
}
return super.onOptionsItemSelected(item);
}
public void setToolbarColor(int color) {
toolbar.setBackgroundColor(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().setStatusBarColor(color);
}
}
@Override
public void setTitle(CharSequence title) {
super.setTitle(title);
if (toolbar == null) return;
toolbar.setTitle(title);
}
@Override
public void setTitle(int titleId) {
super.setTitle(titleId);
if (toolbar == null) return;
toolbar.setTitle(titleId);
}
protected int dp2px(float dpValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/adapter/FragmentPageAdapter.java
================================================
package com.example.httpsender.adapter;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.Arrays;
import java.util.List;
/**
* User: ljx
* Date: 2018/6/9
* Time: 13:53
*/
public class FragmentPageAdapter extends FragmentPagerAdapter {
private List<? extends Fragment> mFragments;
private List<? extends CharSequence> mTitles;
public FragmentPageAdapter(FragmentManager fm, List<? extends Fragment> fragments, String[] titles) {
this(fm, fragments, Arrays.asList(titles));
}
public FragmentPageAdapter(FragmentManager fm, List<? extends Fragment> fragments, List<? extends CharSequence> titles) {
super(fm);
mFragments = fragments;
mTitles = titles;
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/Article.java
================================================
package com.example.httpsender.entity;
/**
* 文章实体类
* User: ljx
* Date: 2019-09-24
* Time: 10:23
*/
public class Article {
/**
* apkLink :
* audit : 1
* author :
* chapterId : 76
* chapterName : 项目架构
* collect : false
* courseId : 13
* desc :
* envelopePic :
* fresh : true
* id : 9300
* link : https://mp.weixin.qq.com/s/_6p6vfce7m5E8AwGDg2cZg
* niceDate : 10小时前
* niceShareDate : 11小时前
* origin :
* prefix :
* projectLink :
* publishTime : 1569255115000
* shareDate : 1569249942000
* shareUser : ZYLAB
* superChapterId : 74
* superChapterName : 热门专题
* tags : []
* title : Android 开发中的架构模式 -- MVC / MVP / MVVM
* type : 0
* userId : 10577
* visible : 1
* zan : 0
*/
private String apkLink;
private int audit;
private String author;
private int chapterId;
private String chapterName;
private boolean collect;
private int courseId;
private String desc;
private String envelopePic;
private boolean fresh;
private int id;
private String link;
private String niceDate;
private String niceShareDate;
private String origin;
private String prefix;
private String projectLink;
private long publishTime;
private long shareDate;
private String shareUser;
private int superChapterId;
private String superChapterName;
private String title;
private int type;
private int userId;
private int visible;
private int zan;
public String getApkLink() {
return apkLink;
}
public int getAudit() {
return audit;
}
public String getAuthor() {
return author;
}
public int getChapterId() {
return chapterId;
}
public String getChapterName() {
return chapterName;
}
public boolean isCollect() {
return collect;
}
public int getCourseId() {
return courseId;
}
public String getDesc() {
return desc;
}
public String getEnvelopePic() {
return envelopePic;
}
public boolean isFresh() {
return fresh;
}
public int getId() {
return id;
}
public String getLink() {
return link;
}
public String getNiceDate() {
return niceDate;
}
public String getNiceShareDate() {
return niceShareDate;
}
public String getOrigin() {
return origin;
}
public String getPrefix() {
return prefix;
}
public String getProjectLink() {
return projectLink;
}
public long getPublishTime() {
return publishTime;
}
public long getShareDate() {
return shareDate;
}
public String getShareUser() {
return shareUser;
}
public int getSuperChapterId() {
return superChapterId;
}
public String getSuperChapterName() {
return superChapterName;
}
public String getTitle() {
return title;
}
public int getType() {
return type;
}
public int getUserId() {
return userId;
}
public int getVisible() {
return visible;
}
public int getZan() {
return zan;
}
public void setApkLink(String apkLink) {
this.apkLink = apkLink;
}
public void setAudit(int audit) {
this.audit = audit;
}
public void setAuthor(String author) {
this.author = author;
}
public void setChapterId(int chapterId) {
this.chapterId = chapterId;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public void setCollect(boolean collect) {
this.collect = collect;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public void setDesc(String desc) {
this.desc = desc;
}
public void setEnvelopePic(String envelopePic) {
this.envelopePic = envelopePic;
}
public void setFresh(boolean fresh) {
this.fresh = fresh;
}
public void setId(int id) {
this.id = id;
}
public void setLink(String link) {
this.link = link;
}
public void setNiceDate(String niceDate) {
this.niceDate = niceDate;
}
public void setNiceShareDate(String niceShareDate) {
this.niceShareDate = niceShareDate;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public void setProjectLink(String projectLink) {
this.projectLink = projectLink;
}
public void setPublishTime(long publishTime) {
this.publishTime = publishTime;
}
public void setShareDate(long shareDate) {
this.shareDate = shareDate;
}
public void setShareUser(String shareUser) {
this.shareUser = shareUser;
}
public void setSuperChapterId(int superChapterId) {
this.superChapterId = superChapterId;
}
public void setSuperChapterName(String superChapterName) {
this.superChapterName = superChapterName;
}
public void setTitle(String title) {
this.title = title;
}
public void setType(int type) {
this.type = type;
}
public void setUserId(int userId) {
this.userId = userId;
}
public void setVisible(int visible) {
this.visible = visible;
}
public void setZan(int zan) {
this.zan = zan;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Article article = (Article) o;
return id == article.id;
}
@Override
public int hashCode() {
return id;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/DownloadTask.java
================================================
package com.example.httpsender.entity;
/**
* User: ljx
* Date: 2019-06-08
* Time: 10:09
*/
public class DownloadTask {
private String url;
private String localPath;
private float progress;
private long currentSize;
private long totalSize;
private long speed;
private long remainingTime;
private int state; //0=未开始 1=等待中 2=下载中 3=暂停中 4=已完成 5=下载失败 6=已取消
public DownloadTask(String url) {
this.url = url;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLocalPath() {
return localPath;
}
public void setLocalPath(String localPath) {
this.localPath = localPath;
}
public long getSpeed() {
return speed;
}
public void setSpeed(long speed) {
this.speed = speed;
}
public long getRemainingTime() {
return remainingTime;
}
public void setRemainingTime(long remainingTime) {
this.remainingTime = remainingTime;
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
}
public long getCurrentSize() {
return currentSize;
}
public void setCurrentSize(long currentSize) {
this.currentSize = currentSize;
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DownloadTask task = (DownloadTask) o;
return url.equals(task.url);
}
@Override
public int hashCode() {
return url.hashCode();
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/ErrorInfo.java
================================================
package com.example.httpsender.entity;
import android.text.TextUtils;
import com.example.httpsender.AppHolder;
import com.example.httpsender.ExceptionHelper;
import com.example.httpsender.R;
import com.example.httpsender.Tip;
import com.google.gson.JsonSyntaxException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeoutException;
import rxhttp.wrapper.exception.HttpStatusCodeException;
import rxhttp.wrapper.exception.ParseException;
/**
* Http请求错误信息
* User: ljx
* Date: 2019-06-26
* Time: 14:26
*/
public class ErrorInfo {
private int errorCode; //仅指服务器返回的错误码
private String errorMsg; //错误文案,网络错误、请求失败错误、服务器返回的错误等文案
private Throwable throwable; //异常信息
public ErrorInfo(Throwable throwable) {
this.throwable = throwable;
String errorMsg = null;
if (throwable instanceof UnknownHostException) {
if (!ExceptionHelper.isNetworkConnected(AppHolder.getInstance())) {
errorMsg = getString(R.string.network_error);
} else {
errorMsg = getString(R.string.notify_no_network);
}
} else if (throwable instanceof SocketTimeoutException || throwable instanceof TimeoutException) {
//前者是通过OkHttpClient设置的超时引发的异常,后者是对单个请求调用timeout方法引发的超时异常
errorMsg = getString(R.string.time_out_please_try_again_later);
} else if (throwable instanceof ConnectException) {
errorMsg = getString(R.string.esky_service_exception);
} else if (throwable instanceof HttpStatusCodeException) { //请求失败异常
String code = throwable.getLocalizedMessage();
if ("416".equals(code)) {
errorMsg = "请求范围不符合要求";
} else {
errorMsg = throwable.getMessage();
}
} else if (throwable instanceof JsonSyntaxException) { //请求成功,但Json语法异常,导致解析失败
errorMsg = "数据解析失败,请稍后再试";
} else if (throwable instanceof ParseException) { // ParseException异常表明请求成功,但是数据不正确
String errorCode = throwable.getLocalizedMessage();
this.errorCode = Integer.parseInt(errorCode);
errorMsg = throwable.getMessage();
if (TextUtils.isEmpty(errorMsg)) errorMsg = errorCode;//errorMsg为空,显示errorCode
} else {
errorMsg = throwable.getMessage();
}
this.errorMsg = errorMsg;
}
public int getErrorCode() {
return errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public Throwable getThrowable() {
return throwable;
}
public boolean show() {
Tip.show(TextUtils.isEmpty(errorMsg) ? throwable.getMessage() : errorMsg);
return true;
}
/**
* @param standbyMsg 备用的提示文案
*/
public boolean show(String standbyMsg) {
Tip.show(TextUtils.isEmpty(errorMsg) ? standbyMsg : errorMsg);
return true;
}
/**
* @param standbyMsg 备用的提示文案
*/
public boolean show(int standbyMsg) {
Tip.show(TextUtils.isEmpty(errorMsg) ? AppHolder.getInstance().getString(standbyMsg) : errorMsg);
return true;
}
public String getString(int resId) {
return AppHolder.getInstance().getString(resId);
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/Location.java
================================================
package com.example.httpsender.entity;
/**
* User: ljx
* Date: 2019-11-18
* Time: 14:51
*/
public class Location {
private double longitude;
private double latitude;
public Location(double longitude, double latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/Name.java
================================================
package com.example.httpsender.entity;
/**
* User: ljx
* Date: 2019-11-18
* Time: 16:19
*/
public class Name {
String name;
public Name(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/NewsDataXml.java
================================================
package com.example.httpsender.entity;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.ArrayList;
import java.util.List;
/**
* User: ljx
* Date: 2019-11-22
* Time: 23:34
*/
@Root(name = "body", strict = false) //name:要解析的xml数据的头部
public class NewsDataXml {
@Attribute
public String copyright; //属性
@ElementList(required = true, inline = true, entry = "route") //标志是集合
public List<NewsXml> newsXmls = new ArrayList<>();
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/NewsXml.java
================================================
package com.example.httpsender.entity;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Root;
/**
* User: ljx
* Date: 2019-11-22
* Time: 23:34
*/
@Root(name = "route", strict = false) //要解析的xml数据的头部
public class NewsXml {
@Attribute
public String tag;
@Attribute
public String title;
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/PageList.java
================================================
package com.example.httpsender.entity;
import java.util.ArrayList;
import java.util.List;
/**
* User: ljx
* Date: 2018/10/21
* Time: 13:16
*/
public class PageList<T> {
private int curPage; //当前页数
private int pageCount; //总页数
private int total; //总条数
private List<T> datas;
public int getCurPage() {
return curPage;
}
public int getPageCount() {
return pageCount;
}
public int getTotal() {
return total;
}
public List<T> getDatas() {
return datas;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public void setTotal(int total) {
this.total = total;
}
public void setDatas(ArrayList<T> datas) {
this.datas = datas;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/Response.java
================================================
package com.example.httpsender.entity;
/**
* User: ljx
* Date: 2018/10/21
* Time: 13:16
*/
public class Response<T> {
private int errorCode;
private String errorMsg;
private T data;
public int getCode() {
return errorCode;
}
public String getMsg() {
return errorMsg;
}
public T getData() {
return data;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public void setData(T data) {
this.data = data;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/Url.kt
================================================
package com.example.httpsender.entity
import rxhttp.wrapper.annotation.DefaultDomain
import rxhttp.wrapper.annotation.Domain
/**
* User: ljx
* Date: 2020/2/27
* Time: 23:55
*/
object Url {
@JvmField
@DefaultDomain //设置为默认域名
var baseUrl = "https://www.wanandroid.com/"
const val UPLOAD_URL = "http://t.xinhuo.com/index.php/Api/Pic/uploadPic"
const val DOWNLOAD_URL = "https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk"
}
================================================
FILE: app/src/main/java/com/example/httpsender/entity/User.java
================================================
package com.example.httpsender.entity;
/**
* User: ljx
* Date: 2019-12-04
* Time: 12:13
*/
public class User {
private static User mUser;
private String token;
public static User get() {
if (mUser == null) {
synchronized (User.class) {
if (mUser == null)
mUser = new User();
}
}
return mUser;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/fragment/AwaitFragment.kt
================================================
package com.example.httpsender.fragment
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.example.httpsender.R
import com.example.httpsender.databinding.AwaitFragmentBinding
import com.example.httpsender.entity.*
import com.example.httpsender.kt.errorMsg
import com.example.httpsender.kt.show
import com.google.gson.Gson
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import rxhttp.*
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toAwaitResponse
import java.io.File
import java.util.*
/**
* 使用 协程(RxHttp + Await) 发请求
*
* ```
* val user = RxHttp.postXxx("/service/...")
* .add("key", "value")
* .toAwait<User>()
* .awaitResult {
* val user = it
* }.onFailure {
* val throwable = it
* }
*```
*
* User: ljx
* Date: 2020/4/24
* Time: 18:16
*/
class AwaitFragment : BaseFragment<AwaitFragmentBinding>(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.await_fragment)
}
override fun AwaitFragmentBinding.onViewCreated(savedInstanceState: Bundle?) {
click = this@AwaitFragment
}
//发送Get请求,获取文章列表
private suspend fun AwaitFragmentBinding.sendGet(view: View) {
RxHttp.get("/article/list/0/json")
.toAwaitResponse<PageList<Article>>()
.toAwaitOkResponse()
.awaitResult {
val list = it.body()
val response = it.raw()
val headers = it.headers()
tvResult.text = Gson().toJson(list)
}.onFailure {
tvResult.text = it.errorMsg
//失败回调
it.show()
}
}
//发送Post表单请求,根据关键字查询文章
private suspend fun AwaitFragmentBinding.sendPostForm(view: View) {
RxHttp.postForm("/article/query/0/json")
.add("k", "性能优化")
.toAwaitResponse<PageList<Article>>()
.awaitResult {
tvResult.text = Gson().toJson(it)
}.onFailure {
tvResult.text = it.errorMsg
//失败回调
it.show()
}
}
//发送Post Json请求,此接口不通,通过日志可以看到,发送出去的json对象
private suspend fun AwaitFragmentBinding.sendPostJson(view: View) {
/*
发送以下User对象
{"name":"张三","sex":1,"height":180,"weight":70,
"interest":["羽毛球","游泳"],
"location":{"latitude":30.7866,"longitude":120.6788},
"address":{"street":"科技园路.","city":"江苏苏州","country":"中国"}}
*/
val interestList: MutableList<String> = ArrayList() //爱好
interestList.add("羽毛球")
interestList.add("游泳")
val address = """
{"street":"科技园路.","city":"江苏苏州","country":"中国"}
""".trimIndent()
RxHttp.postJson("/article/list/0/json")
.add("name", "张三")
.add("sex", 1)
.addAll("""{"height":180,"weight":70}""") //通过addAll系列方法添加多个参数
.add("interest", interestList) //添加数组对象
.add("location", Location(120.6788, 30.7866)) //添加位置对象
.addJsonElement("address", address) //通过字符串添加一个对象
.toAwaitString()
.awaitResult {
tvResult.text = it
}.onFailure {
tvResult.text = it.errorMsg
//失败回调
it.show()
}
}
//发送Post JsonArray请求,通过日志可以看到,发送出去的json数组
private suspend fun AwaitFragmentBinding.sendPostJsonArray(view: View) {
/*
发送以下Json数组
[{"name":"张三"},{"name":"李四"},{"name":"王五"},{"name":"赵六"},{"name":"杨七"}]
*/
val names: MutableList<Name?> = ArrayList()
names.add(Name("赵六"))
names.add(Name("杨七"))
RxHttp.postJsonArray("/article/list/0/json")
.add("name", "张三")
.add(Name("李四"))
.addJsonElement("""{"name":"王五"}""")
.addAll(names)
.toAwaitString()
.awaitResult {
tvResult.text = it
}.onFailure {
tvResult.text = it.errorMsg
//失败回调
it.show()
}
}
//此接口不同,但通过日志可以看到,发送出去的是xml数据,如果收到也是xml数据,则会自动解析为我们指定的对象
private suspend fun AwaitFragmentBinding.xmlConverter(view: View) {
RxHttp.postBody("http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni")
.setBody(Name("张三"))
.setXmlConverter()
.toAwait<NewsDataXml>()
.awaitResult {
tvResult.text = Gson().toJson(it)
}.onFailure {
tvResult.text = it.errorMsg
//失败回调
it.show()
}
}
/**
* android 10之前 或 沙盒目录(Android/data/packageName/)下的文件上传
*
* 注意:这里并非通过 [Await] 实现的, 而是通过 [Flow] 监听的进度,因为在监听上传进度这块,Flow性能更优,且更简单
*
* 如不需要监听进度,toFlow 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.upload(v: View) {
RxHttp.postForm(Url.UPLOAD_URL)
.addFile("file", File("xxxx/1.png"))
.toFlow<String>()
.onProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
//失败回调
it.show()
}.collect {
tvResult.append("\n上传成功 : $it")
}
}
/**
* android 10 及以上文件上传 ,兼容Android 10以下
*
* 注意:这里并非通过 [Await] 实现的, 而是通过 [Flow] 监听的进度,因为在监听上传进度这块,Flow性能更优,且更简单
*
* 如不需要监听进度,toFlow 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.uploadAndroid10(v: View) {
//真实环境,需要调用文件选择器,拿到Uri对象
val uri = Uri.parse("content://media/external/downloads/13417")
RxHttp.postForm(Url.UPLOAD_URL)
.addPart(requireContext(), "file", uri)
.toFlow<String>()
.onProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
//失败回调
it.show()
}.collect {
tvResult.append("\n上传成功 : $it")
}
}
/**
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
*
* 如不需要监听下载进度,toDownload 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.download(view: View) {
// val destPath = "${requireContext().externalCacheDir}/${System.currentTimeMillis()}.apk"
// RxHttp.get(Url.DOWNLOAD_URL)
// .toDownloadAwait(destPath) {
// val currentProgress = it.progress //当前进度 0-100
// val currentSize = it.currentSize //当前已下载的字节大小
// val totalSize = it.totalSize //要下载的总字节大小
// tvResult.append(it.toString())
// }.awaitResult {
// tvResult.append("\n下载完成, $it")
// }.onFailure {
// //异常回调
// tvResult.append("\n${it.errorMsg}")
// it.show()
// }
}
/**
* 断点下载
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
* 如不需要监听下载进度,toDownload 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.appendDownload(view: View) {
// val destPath = "${requireContext().externalCacheDir}/Miaobo.apk"
// RxHttp.get(Url.DOWNLOAD_URL)
// .toDownloadAwait(destPath, true) {
// val currentProgress = it.progress //当前进度 0-100
// val currentSize = it.currentSize //当前已下载的字节大小
// val totalSize = it.totalSize //要下载的总字节大小
// tvResult.append(it.toString())
// }.awaitResult {
// tvResult.append("\n下载完成, $it")
// }.onFailure {
// //异常回调
// tvResult.append("\n${it.errorMsg}")
// it.show()
// }
}
/**
* Android 10 及以上下载,兼容Android 10以下
* 如不需要监听下载进度,toDownload 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.downloadAndroid10(view: View) {
// val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
// RxHttp.get(Url.DOWNLOAD_URL)
// .toDownloadAwait(factory) {
// val currentProgress = it.progress //当前进度 0-100
// val currentSize = it.currentSize //当前已下载的字节大小
// val totalSize = it.totalSize //要下载的总字节大小
// tvResult.append(it.toString())
// }.awaitResult {
// tvResult.append("\n下载完成, $it")
// }.onFailure {
// //异常回调
// tvResult.append("\n${it.errorMsg}")
// it.show()
// }
}
/**
* Android 10 及以上断点下载,兼容Android 10以下
* 如不需要监听下载进度,toDownload 方法不要传进度回调即可
*/
private suspend fun AwaitFragmentBinding.appendDownloadAndroid10(view: View) {
// val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
// RxHttp.get(Url.DOWNLOAD_URL)
// .toDownloadAwait(factory, true) {
// val currentProgress = it.progress //当前进度 0-100
// val currentSize = it.currentSize //当前已下载的字节大小
// val totalSize = it.totalSize //要下载的总字节大小
// tvResult.append(it.toString())
// }.awaitResult {
// tvResult.append("\n下载完成, $it")
// }.onFailure {
// //异常回调
// tvResult.append("\n${it.errorMsg}")
// it.show()
// }
}
private fun AwaitFragmentBinding.clearLog(view: View) {
tvResult.text = ""
tvResult.setBackgroundColor(Color.TRANSPARENT)
}
override fun onClick(v: View) {
mBinding.run {
lifecycleScope.launch {
when (v.id) {
R.id.sendGet -> sendGet(v)
R.id.sendPostForm -> sendPostForm(v)
R.id.sendPostJson -> sendPostJson(v)
R.id.sendPostJsonArray -> sendPostJsonArray(v)
R.id.xmlConverter -> xmlConverter(v)
R.id.upload -> upload(v)
R.id.upload10 -> uploadAndroid10(v)
R.id.download -> download(v)
R.id.download_append -> appendDownload(v)
R.id.download10 -> downloadAndroid10(v)
R.id.download10_append -> appendDownloadAndroid10(v)
R.id.bt_clear -> clearLog(v)
}
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/fragment/BaseFragment.kt
================================================
package com.example.httpsender.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
/**
* User: ljx
* Date: 2020/6/2
* Time: 11:45
*/
abstract class BaseFragment<T : ViewDataBinding> : Fragment() {
@LayoutRes
private var layoutId = 0
protected lateinit var mBinding: T
fun setContentView(@LayoutRes layoutId: Int) {
this.layoutId = layoutId
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
mBinding = DataBindingUtil.inflate(inflater, layoutId, container, false)
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mBinding.onViewCreated(savedInstanceState)
}
open fun T.onViewCreated(savedInstanceState: Bundle?) {
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/fragment/FlowFragment.kt
================================================
package com.example.httpsender.fragment
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.example.httpsender.R
import com.example.httpsender.databinding.FlowFragmentBinding
import com.example.httpsender.entity.Article
import com.example.httpsender.entity.Location
import com.example.httpsender.entity.Name
import com.example.httpsender.entity.NewsDataXml
import com.example.httpsender.entity.PageList
import com.example.httpsender.entity.Url
import com.example.httpsender.kt.errorMsg
import com.example.httpsender.kt.show
import com.example.httpsender.parser.Android10DownloadFactory
import com.google.gson.Gson
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import rxhttp.toDownloadFlow
import rxhttp.toFlow
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toFlowResponse
import java.io.File
/**
* 使用 协程(RxHttp + Flow) 发请求
*
* ```
* RxHttp.postXxx("/service/...")
* .add("key", "value")
* .toFlow<User>()
* .catch {
* val throwable = it
* }.collect {
* val user = it
* }
*```
* User: ljx
* Date: 2021/9/18
* Time: 20:16
*/
class FlowFragment : BaseFragment<FlowFragmentBinding>(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.flow_fragment)
}
override fun FlowFragmentBinding.onViewCreated(savedInstanceState: Bundle?) {
click = this@FlowFragment
}
//发送Get请求,获取文章列表
private suspend fun FlowFragmentBinding.sendGet(view: View) {
RxHttp.get("/article/list/0/json")
.toFlowResponse<PageList<Article>>()
.catch {
tvResult.text = it.errorMsg
it.show()
}.collect {
tvResult.text = Gson().toJson(it)
}
}
//发送Post表单请求,根据关键字查询文章
private suspend fun FlowFragmentBinding.sendPostForm(view: View) {
RxHttp.postForm("/article/query/0/json")
.add("k", "性能优化")
.toFlowResponse<PageList<Article>>()
.catch {
tvResult.text = it.errorMsg
it.show()
}.collect {
tvResult.text = Gson().toJson(it)
}
}
//发送Post Json请求,此接口不通,通过日志可以看到,发送出去的json对象
private suspend fun FlowFragmentBinding.sendPostJson(view: View) {
/*
发送以下User对象
{"name":"张三","sex":1,"height":180,"weight":70,
"interest":["羽毛球","游泳"],
"location":{"latitude":30.7866,"longitude":120.6788},
"address":{"street":"科技园路.","city":"江苏苏州","country":"中国"}}
*/
val interestList: MutableList<String> = ArrayList() //爱好
interestList.add("羽毛球")
interestList.add("游泳")
val address = """
{"street":"科技园路.","city":"江苏苏州","country":"中国"}
""".trimIndent()
RxHttp.postJson("/article/list/0/json")
.add("name", "张三")
.add("sex", 1)
.addAll("""{"height":180,"weight":70}""") //通过addAll系列方法添加多个参数
.add("interest", interestList) //添加数组对象
.add("location", Location(120.6788, 30.7866)) //添加位置对象
.addJsonElement("address", address) //通过字符串添加一个对象
.toFlow<String>()
.catch {
tvResult.text = it.errorMsg
it.show()
}.collect {
tvResult.text = it
}
}
//发送Post JsonArray请求,通过日志可以看到,发送出去的json数组
private suspend fun FlowFragmentBinding.sendPostJsonArray(view: View) {
/*
发送以下Json数组
[{"name":"张三"},{"name":"李四"},{"name":"王五"},{"name":"赵六"},{"name":"杨七"}]
*/
val names: MutableList<Name?> = ArrayList()
names.add(Name("赵六"))
names.add(Name("杨七"))
RxHttp.postJsonArray("/article/list/0/json")
.add("name", "张三")
.add(Name("李四"))
.addJsonElement("""{"name":"王五"}""")
.addAll(names)
.toFlow<String>()
.catch {
tvResult.text = it.errorMsg
it.show()
}.collect {
tvResult.text = it
}
}
//此接口不同,但通过日志可以看到,发送出去的是xml数据,如果收到也是xml数据,则会自动解析为我们指定的对象
private suspend fun FlowFragmentBinding.xmlConverter(view: View) {
RxHttp.postBody("http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni")
.setBody(Name("张三"))
.setXmlConverter()
.toFlow<NewsDataXml>()
.catch {
tvResult.text = it.errorMsg
it.show()
}.collect {
tvResult.text = Gson().toJson(it)
}
}
/**
* android 10之前 或 沙盒目录(Android/data/packageName/)下的文件上传
*
* 如不需要监听进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.upload(v: View) {
RxHttp.postForm(Url.UPLOAD_URL)
.addFile("file", File("xxxx/1.png"))
.toFlow<String>()
.onProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
//失败回调
it.show()
}.collect {
tvResult.append("\n上传成功 : $it")
}
}
/**
* android 10 及以上文件上传 ,兼容Android 10以下
*
* 如不需要监听进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.uploadAndroid10(v: View) {
//真实环境,需要调用文件选择器,拿到Uri对象
val uri = Uri.parse("content://media/external/downloads/13417")
RxHttp.postForm(Url.UPLOAD_URL)
.addPart(requireContext(), "file", uri)
.toFlow<String>()
.onProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
//失败回调
it.show()
}.collect {
tvResult.append("\n上传成功 : $it")
}
}
/**
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
*
* 如不需要监听下载进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.download(view: View) {
val destPath = "${requireContext().externalCacheDir}/${System.currentTimeMillis()}.apk"
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadFlow(destPath)
.onProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}") //异常回调
it.show()
}.collect {
tvResult.append("\n下载完成, $it")
}
}
/**
* 断点下载
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
*
* 如不需要监听下载进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.appendDownload(view: View) {
val destPath = "${requireContext().externalCacheDir}/Miaobo.apk"
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadFlow(destPath, true)
.onProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
it.show()
}.collect {
tvResult.append("\n下载完成, $it")
}
}
/**
* Android 10 及以上下载,兼容Android 10以下
*
* 如不需要监听下载进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.downloadAndroid10(view: View) {
val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadFlow(factory)
.onProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}.catch {
tvResult.append("\n${it.errorMsg}")
it.show()
}.collect {
tvResult.append("\n下载完成, $it")
}
}
/**
* Android 10 及以上断点下载,兼容Android 10以下
*
* 如不需要监听下载进度,toFlow 方法不要传进度回调即可
*/
private suspend fun FlowFragmentBinding.appendDownloadAndroid10(view: View) {
val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadFlow(factory, true)
.onProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}.catch {
//异常回调
tvResult.append("\n${it.errorMsg}")
it.show()
}.collect {
tvResult.append("\n下载完成, $it")
}
}
private fun FlowFragmentBinding.clearLog(view: View) {
tvResult.text = ""
tvResult.setBackgroundColor(Color.TRANSPARENT)
}
override fun onClick(v: View) {
mBinding.run {
lifecycleScope.launch {
when (v.id) {
R.id.sendGet -> sendGet(v)
R.id.sendPostForm -> sendPostForm(v)
R.id.sendPostJson -> sendPostJson(v)
R.id.sendPostJsonArray -> sendPostJsonArray(v)
R.id.xmlConverter -> xmlConverter(v)
R.id.upload -> upload(v)
R.id.upload10 -> uploadAndroid10(v)
R.id.download -> download(v)
R.id.download_append -> appendDownload(v)
R.id.download10 -> downloadAndroid10(v)
R.id.download10_append -> appendDownloadAndroid10(v)
R.id.bt_clear -> clearLog(v)
}
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/fragment/MultiDownloadFragment.java
================================================
package com.example.httpsender.fragment;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.example.httpsender.DownloadMultiAdapter;
import com.example.httpsender.DownloadMultiAdapter.OnItemClickListener;
import com.example.httpsender.R;
import com.example.httpsender.Tip;
import com.example.httpsender.databinding.MultiDownloadFragmentBinding;
import com.example.httpsender.entity.DownloadTask;
import com.example.httpsender.vm.MultiTaskDownloader;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
/**
* User: ljx
* Date: 2021/9/25
* Time: 18:08
*/
public class MultiDownloadFragment extends BaseFragment<MultiDownloadFragmentBinding> implements OnItemClickListener<DownloadTask>, OnClickListener {
private final String[] downloadUrl = {
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/uS12nZLR.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/BYGanTMW.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/Iu9hZLL8.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/DdKLk5VX.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/Byww5X8k.ts",
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?111",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?222",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?333",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?444",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?555",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?666",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?777",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?888",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?999",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?101",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?102",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?103",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?104",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?105",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?106",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?107",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk?108",//探探
"https://apk-ssl.tancdn.com/3.5.3_276/%E6%8E%A2%E6%8E%A2.apk",//探探
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/OUkREagY.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/ZJUsgPSd.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/I5ivzoXR.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/PFPXapY7.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/tJj2JTVy.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/mj2fFYjH.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/MOXijkzw.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/uiwVyFej.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/HijAOXaK.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/h2mFS6ef.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/vf8fjmJd.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/0jsVXFSa.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/aZfnIVnP.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/l7cddTCQ.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/QaMi23d0.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/ljLywei6.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/FQpwzm4U.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/4oW2C2iZ.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/57OL3KeG.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/vYlV9nTw.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/XUmd5HWF.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/btVvEY5r.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/eJRKGoaP.ts",
// "https://hnzy4.jinhaiwzhs.com:65/20210625/mndoRF1O/2000kb/hls/iz5kx1X1.ts",
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multi_download_fragment);
}
@Override
public void onViewCreated(@NotNull MultiDownloadFragmentBinding binding, @Nullable Bundle savedInstanceState) {
super.onViewCreated(binding, savedInstanceState);
binding.setClick(this);
ArrayList<DownloadTask> allTask = new ArrayList<>(); //所有下载任务
for (int i = 0; i < downloadUrl.length; i++) {
String url = downloadUrl[i];
DownloadTask task = new DownloadTask(url);
String suffix = url.substring(url.lastIndexOf("."));
task.setLocalPath(getContext().getExternalCacheDir() + "/" + i + suffix);
allTask.add(task);
}
RecyclerView recyclerView = binding.recyclerView;
MultiTaskDownloader.addTasks(allTask);
DownloadMultiAdapter multiAdapter = new DownloadMultiAdapter(MultiTaskDownloader.getAllTask());
multiAdapter.setOnItemClickListener(this);
recyclerView.setAdapter(multiAdapter);
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
MultiTaskDownloader.getLiveTask().observe(getViewLifecycleOwner(), task -> {
int index = MultiTaskDownloader.getAllTask().indexOf(task);
if (index != -1) {
//任务有更新,刷新单个item
multiAdapter.notifyItemChanged(index);
}
});
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.start_all) {
MultiTaskDownloader.startAllDownloadTask();
} else if (id == R.id.cancel_all) {
MultiTaskDownloader.cancelAllTask();
}
}
@Override
public void onItemClick(View view, DownloadTask task, int position) {
if (view.getId() == R.id.bt_pause) {
int curState = task.getState(); //任务当前状态
if (curState == MultiTaskDownloader.IDLE //未开始->开始下载
|| curState == MultiTaskDownloader.PAUSED //暂停下载->继续下载
|| curState == MultiTaskDownloader.CANCEL //已取消->重新开始下载
|| curState == MultiTaskDownloader.FAIL //下载失败->重新下载
) {
MultiTaskDownloader.download(task);
} else if (curState == MultiTaskDownloader.WAITING) { //等待中->取消下载
MultiTaskDownloader.removeWaitTask(task);
} else if (curState == MultiTaskDownloader.DOWNLOADING) { //下载中->暂停下载
MultiTaskDownloader.pauseTask(task);
} else if (curState == MultiTaskDownloader.COMPLETED) { //任务已完成
Tip.show("该任务已完成");
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/fragment/RxJavaFragment.kt
================================================
package com.example.httpsender.fragment
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.view.View
import com.example.httpsender.R
import com.example.httpsender.databinding.RxjavaFragmentBinding
import com.example.httpsender.entity.Article
import com.example.httpsender.entity.Location
import com.example.httpsender.entity.Name
import com.example.httpsender.entity.NewsDataXml
import com.example.httpsender.entity.PageList
import com.example.httpsender.entity.Url
import com.example.httpsender.kt.errorMsg
import com.example.httpsender.kt.show
import com.example.httpsender.parser.Android10DownloadFactory
import com.google.gson.Gson
import com.rxjava.rxlife.life
import com.rxjava.rxlife.lifeOnMain
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toObservable
import rxhttp.wrapper.param.toObservableResponse
import java.io.File
/**
* 使用 RxHttp + RxJava 发请求
*
* ```
* RxHttp.postXxx("/service/...")
* .add("key", "value")
* .toObservable<User>()
* .subscribe(user -> {
*
* }, throwable -> {
*
* })
* ```
* User: ljx
* Date: 2020/4/24
* Time: 18:16
*/
class RxJavaFragment : BaseFragment<RxjavaFragmentBinding>(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.rxjava_fragment)
}
override fun RxjavaFragmentBinding.onViewCreated(savedInstanceState: Bundle?) {
click = this@RxJavaFragment
}
//发送Get请求,获取文章列表
fun RxjavaFragmentBinding.sendGet(view: View?) {
RxHttp.get("/article/list/0/json")
.addQuery("aa")
.addQuery("bb","")
.toObservableResponse<PageList<Article>>()
.lifeOnMain(this@RxJavaFragment)
.subscribe({
tvResult.text = Gson().toJson(it)
}, {
tvResult.text = it.errorMsg
it.show()
})
}
//发送Post表单请求,根据关键字查询文章
fun RxjavaFragmentBinding.sendPostForm(view: View?) {
RxHttp.postForm("/article/query/0/json")
.add("k", "性能优化")
.toObservableResponse<PageList<Article>>()
.lifeOnMain(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.text = Gson().toJson(it)
}, {
tvResult.text = it.errorMsg
it.show()
})
}
//发送Post Json请求,此接口不通,通过日志可以看到,发送出去的json对象
fun RxjavaFragmentBinding.sendPostJson(view: View?) {
//发送以下User对象
/*
{
"name": "张三",
"sex": 1,
"height": 180,
"weight": 70,
"interest": [
"羽毛球",
"游泳"
],
"location": {
"latitude": 30.7866,
"longitude": 120.6788
},
"address": {
"street": "科技园路.",
"city": "江苏苏州",
"country": "中国"
}
}
*/
val interestList: MutableList<String> = ArrayList() //爱好
interestList.add("羽毛球")
interestList.add("游泳")
val address = "{\"street\":\"科技园路.\",\"city\":\"江苏苏州\",\"country\":\"中国\"}"
RxHttp.postJson("/article/list/0/json")
.add("name", "张三")
.add("sex", 1)
.addAll("{\"height\":180,\"weight\":70}") //通过addAll系列方法添加多个参数
.add("interest", interestList) //添加数组对象
.add("location", Location(120.6788, 30.7866)) //添加位置对象
.addJsonElement("address", address) //通过字符串添加一个对象
.toObservableString()
.lifeOnMain(this@RxJavaFragment)//感知生命周期,并在主线程回调
.subscribe({
tvResult.text = it
}, {
tvResult.text = it.errorMsg
it.show()
})
}
//发送Post JsonArray请求,通过日志可以看到,发送出去的json数组
fun RxjavaFragmentBinding.sendPostJsonArray(view: View?) {
//发送以下Json数组
/*
[
{
"name": "张三"
},
{
"name": "李四"
},
{
"name": "王五"
},
{
"name": "赵六"
},
{
"name": "杨七"
}
]
*/
val names: MutableList<Name?> = ArrayList()
names.add(Name("赵六"))
names.add(Name("杨七"))
RxHttp.postJsonArray("/article/list/0/json")
.add("name", "张三")
.add(Name("李四"))
.addJsonElement("{\"name\":\"王五\"}")
.addAll(names)
.toObservableString()
.lifeOnMain(this@RxJavaFragment)
.subscribe({
tvResult.text = it
}, {
tvResult.text = it.errorMsg
//失败回调
it.show()
})
}
//此接口不同,但通过日志可以看到,发送出去的是xml数据,如果收到也是xml数据,则会自动解析为我们指定的对象
fun RxjavaFragmentBinding.xmlConverter(view: View?) {
RxHttp.postBody("http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni")
.setBody(Name("张三"))
.setXmlConverter()
.toObservable<NewsDataXml>()
.lifeOnMain(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.text = Gson().toJson(it)
}, {
tvResult.text = it.errorMsg
//失败回调
it.show()
})
}
/**
* android 10之前 或 沙盒目录(Android/data/packageName/)下的文件上传,如不需要监听进度,注释掉 upload 方法即可
*/
private fun RxjavaFragmentBinding.upload(v: View) {
RxHttp.postForm(Url.UPLOAD_URL)
.addFile("file", File("xxxx/1.png"))
.toObservableString()
.onMainProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //页面销毁,自动关闭请求
.subscribe({
tvResult.append("\n上传成功 : $it")
}, {
tvResult.append("\n${it.errorMsg}")
it.show()
})
}
/**
* android 10 及以上文件上传 ,兼容Android 10以下,如不需要监听进度,注释掉 upload 方法即可
*/
private fun RxjavaFragmentBinding.uploadAndroid10(v: View) {
//真实环境,需要调用文件选择器,拿到Uri对象
val uri = Uri.parse("content://media/external/downloads/13417")
RxHttp.postForm(Url.UPLOAD_URL)
.addPart(requireContext(), "file", uri)
.toObservableString()
.onMainProgress {
//上传进度回调,0-100,仅在进度有更新时才会回调
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已上传的字节大小
val totalSize = it.totalSize //要上传的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //页面销毁,自动关闭请求
.subscribe({
tvResult.append("\n上传成功 : $it")
}, {
tvResult.append("\n${it.errorMsg}") //失败回调
it.show()
})
}
/**
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
*
* 如不需要监听下载进度,asDownload 方法不要传进度回调即可
*/
private fun RxjavaFragmentBinding.download(view: View) {
val destPath = "${requireContext().externalCacheDir}/${System.currentTimeMillis()}.apk"
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadObservable(destPath)
.onMainProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.append("\n下载完成, $it")
}, {
//下载失败
tvResult.append("\n${it.errorMsg}")
it.show()
})
}
/**
* 断点下载
* Android 10以下 或 下载文件到沙盒目录下,下载可以直接传入file的绝对路径
* 如不需要监听下载进度,asAppendDownload 方法不要传进度回调即可
*/
private fun RxjavaFragmentBinding.appendDownload(view: View) {
val destPath = "${requireContext().externalCacheDir}/Miaobo.apk"
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadObservable(destPath, true)
.onMainProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.append("\n下载完成, $it")
}, {
//下载失败
tvResult.append("\n${it.errorMsg}")
it.show()
})
}
/**
* Android 10 及以上下载,兼容Android 10以下
* 如不需要监听下载进度,asDownload 方法不要传进度回调即可
*/
private fun RxjavaFragmentBinding.downloadAndroid10(view: View) {
val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadObservable(factory)
.onMainProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.append("\n下载完成, $it")
}, {
//下载失败
tvResult.append("\n${it.errorMsg}")
it.show()
})
}
/**
* Android 10 及以上断点下载,兼容Android 10以下
* 如不需要监听下载进度,asAppendDownload 方法不要传进度回调即可
*/
private fun RxjavaFragmentBinding.appendDownloadAndroid10(view: View) {
val factory = Android10DownloadFactory(requireContext(), "miaobo.apk")
RxHttp.get(Url.DOWNLOAD_URL)
.toDownloadObservable(factory, true)
.onMainProgress {
val currentProgress = it.progress //当前进度 0-100
val currentSize = it.currentSize //当前已下载的字节大小
val totalSize = it.totalSize //要下载的总字节大小
tvResult.append("\n$it")
}
.life(this@RxJavaFragment) //感知生命周期,并在主线程回调
.subscribe({
tvResult.append("\n下载完成, $it")
}, {
//下载失败
tvResult.append("\n${it.errorMsg}")
it.show()
})
}
private fun RxjavaFragmentBinding.clearLog(view: View?) {
tvResult.text = ""
tvResult.setBackgroundColor(Color.TRANSPARENT)
}
override fun onClick(v: View) {
mBinding.apply {
when (v.id) {
R.id.sendGet -> sendGet(v)
R.id.sendPostForm -> sendPostForm(v)
R.id.sendPostJson -> sendPostJson(v)
R.id.sendPostJsonArray -> sendPostJsonArray(v)
R.id.xmlConverter -> xmlConverter(v)
R.id.upload -> upload(v)
R.id.upload10 -> uploadAndroid10(v)
R.id.download -> download(v)
R.id.download_append -> appendDownload(v)
R.id.download10 -> downloadAndroid10(v)
R.id.download10_append -> appendDownloadAndroid10(v)
R.id.bt_clear -> clearLog(v)
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/interceptor/RedirectInterceptor.java
================================================
package com.example.httpsender.interceptor;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
* 处理重定向的拦截器,非必须
* User: ljx
* Date: 2019-12-17
* Time: 23:24
*/
public class RedirectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
okhttp3.Request request = chain.request();
Response response = chain.proceed(request);
int code = response.code();
if (code == 308) {
//获取重定向的地址
String location = response.headers().get("Location");
//重新构建请求
Request newRequest = request.newBuilder().url(location).build();
response.close();
response = chain.proceed(newRequest);
}
return response;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/interceptor/TokenInterceptor.java
================================================
package com.example.httpsender.interceptor;
import com.example.httpsender.entity.User;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import rxhttp.wrapper.param.RxHttp;
/**
* token 失效,自动刷新token,然后再次发送请求,用户无感知
* User: ljx
* Date: 2019-12-04
* Time: 11:56
*/
public class TokenInterceptor implements Interceptor {
//保存刷新后的token
private final AtomicReference<String> atomicToken = new AtomicReference<>();
//token刷新时间
@NotNull
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response originalResponse = chain.proceed(request);
String code = originalResponse.header("xxx"); //其中xxx,自己跟服务端协定
if ("-1".equals(code)) { //token 失效 这里根据自己的业务需求写判断条件
atomicToken.set(null);
return handleTokenInvalid(chain, request);
}
return originalResponse;
}
//处理token失效问题, 同步刷新
private Response handleTokenInvalid(Chain chain, Request request) throws IOException {
boolean success = refreshToken();
Request newRequest;
if (success) { //刷新成功,重新添加token
newRequest = request.newBuilder()
.header("xxx", atomicToken.get()) //其中xxx,自己跟服务端协定
.build();
} else {
newRequest = request;
}
return chain.proceed(newRequest);
}
//刷新token, 考虑到有并发情况,故这里需要加锁
private boolean refreshToken() {
//token不等于null,说明已经刷新
if (atomicToken.get() != null) return true;
synchronized (this) {
//再次判断是否已经刷新
if (atomicToken.get() != null) return true;
try {
//根据自己业务,同步刷新token, 注意这里千万不能异步
String token = RxHttp.postForm("/refreshToken/...")
.executeString();
atomicToken.set(token);
User.get().setToken(token); //保存最新的token
return true;
} catch (IOException e) {
return false;
}
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/kt/Activity.kt
================================================
package com.example.httpsender.kt
import android.app.Activity
import android.content.Intent
import androidx.fragment.app.Fragment
import kotlin.reflect.KClass
/**
* User: ljx
* Date: 2020/5/15
* Time: 16:33
*/
fun <T : Activity> Activity.startActivity(clazz: KClass<T>, block: (Intent.() -> Unit)? = null) {
val intent = Intent(this, clazz.java).apply {
block?.invoke(this)
}
startActivity(intent)
}
fun <T : Activity> Fragment.startActivity(clazz: KClass<T>, block: (Intent.() -> Unit)? = null) {
val intent = Intent(activity, clazz.java).apply {
block?.invoke(this)
}
startActivity(intent)
}
================================================
FILE: app/src/main/java/com/example/httpsender/kt/KotlinExtensions.kt
================================================
package com.example.httpsender.kt
import android.content.Context
import android.net.ConnectivityManager
import com.example.httpsender.AppHolder
import com.example.httpsender.Tip
import com.google.gson.JsonSyntaxException
import kotlinx.coroutines.TimeoutCancellationException
import rxhttp.wrapper.exception.HttpStatusCodeException
import rxhttp.wrapper.exception.ParseException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeoutException
/**
* User: ljx
* Date: 2020-02-07
* Time: 21:04
*/
fun Throwable.show() {
errorMsg.show()
}
fun String.show() {
Tip.show(this)
}
val Throwable.errorCode: Int
get() =
when (this) {
is HttpStatusCodeException -> this.statusCode //Http状态码异常
is ParseException -> this.errorCode.toIntOrNull() ?: -1 //业务code异常
else -> -1
}
val Throwable.errorMsg: String
get() {
return if (this is UnknownHostException) { //网络异常
if (!isNetworkConnected(AppHolder.getInstance()))
"当前无网络,请检查你的网络设置"
else
"网络连接不可用,请稍后重试!"
} else if (
this is SocketTimeoutException //okhttp全局设置超时
|| this is TimeoutException //rxjava中的timeout方法超时
|| this is TimeoutCancellationException //协程超时
) {
"连接超时,请稍后再试"
} else if (this is ConnectException) {
"网络不给力,请稍候重试!"
} else if (this is HttpStatusCodeException) { //请求失败异常
"Http状态码异常 $message"
} else if (this is JsonSyntaxException) { //请求成功,但Json语法异常,导致解析失败
"数据解析失败,请检查数据是否正确"
} else if (this is ParseException) { // ParseException异常表明请求成功,但是数据不正确
this.message ?: errorCode //msg为空,显示code
} else {
message ?: this.toString()
}
}
private fun isNetworkConnected(context: Context): Boolean {
val mConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val mNetworkInfo = mConnectivityManager.activeNetworkInfo
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable
}
return false
}
================================================
FILE: app/src/main/java/com/example/httpsender/kt/Uri.kt
================================================
package com.example.httpsender.kt
import android.content.Context
import android.net.Uri
import android.provider.MediaStore
import android.util.Log
/**
* User: ljx
* Date: 2020/9/24
* Time: 15:33
*/
fun Uri.dimQuery(context: Context, displayName: String) {
context.contentResolver.query(this, null,
"_display_name LIKE '%$displayName%'",null, null)?.use {
while (it.moveToNext()) {
val id = it.getString(it.getColumnIndex(MediaStore.MediaColumns._ID))
val name = it.getString(it.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME))
val data = it.getString(it.getColumnIndex(MediaStore.MediaColumns.DATA))
//注意: 通过这种方式获取的文件size,在文件被手动删除后,读取到的是不准确的
val size = it.getString(it.getColumnIndex(MediaStore.MediaColumns.SIZE))
val dateAdded = it.getString(it.getColumnIndex(MediaStore.MediaColumns.DATE_ADDED))
val dateModified = it.getString(it.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED))
Log.e("LJX", "id=$id size=$size name=$name data=$data dateAdded=$dateAdded dateModified=$dateModified")
}
}
}
fun Uri.dimDelete(context: Context, displayName: String) {
val delete = context.contentResolver.delete(this, "_display_name LIKE '%$displayName%'", null)
Log.e("LJX", "delete=$delete")
}
fun Uri.delete(context: Context, displayName: String) {
val delete = context.contentResolver.delete(this, "_display_name=?", arrayOf(displayName))
Log.e("LJX", "delete=$delete")
}
================================================
FILE: app/src/main/java/com/example/httpsender/param/GetEncryptParam.java
================================================
package com.example.httpsender.param;
import android.graphics.Point;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import okhttp3.HttpUrl;
import rxhttp.wrapper.annotation.Param;
import rxhttp.wrapper.entity.KeyValuePair;
import rxhttp.wrapper.param.Method;
import rxhttp.wrapper.param.NoBodyParam;
/**
* 加密get请求
* User: ljx
* Date: 2019-09-12
* Time: 17:25
*/
@Param(methodName = "getEncrypt")
public class GetEncryptParam extends NoBodyParam {
public GetEncryptParam(String url) {
super(url, Method.GET);
}
@SafeVarargs
public final <T extends Point, R extends CharSequence> GetEncryptParam test(List<R> a, Map<T, R> map, T[]... b) throws IOException, IllegalArgumentException {
return this;
}
@Override
public HttpUrl getHttpUrl() {
StringBuilder paramsBuilder = new StringBuilder(); //存储加密后的参数
List<KeyValuePair> queryParam = getQueryParam();
if (queryParam != null) {
for (KeyValuePair pair : getQueryParam()) {
//这里遍历所有添加的参数,可对参数进行加密操作
String key = pair.getKey();
Object value = pair.getValue();
//加密逻辑自己写
}
}
String simpleUrl = getSimpleUrl(); //拿到请求Url
if (paramsBuilder.length() == 0) return HttpUrl.get(simpleUrl);
return HttpUrl.get(simpleUrl + "?" + paramsBuilder); //将加密后的参数和url组拼成HttpUrl对象并返回
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/param/PostEncryptFormParam.java
================================================
package com.example.httpsender.param;
import rxhttp.wrapper.annotation.Param;
import rxhttp.wrapper.param.FormParam;
import rxhttp.wrapper.param.Method;
/**
* 此类中自己声明的所有public方法(构造方法除外)都会在RxHttp$PostEncryptFormParam类中一一生成,
* 并一一对应调用。如: RxHttp$PostEncryptFormParam.test(int,int)方法内部会调用本类的test(int,int)方法
* User: ljx
* Date: 2019-09-11
* Time: 11:52
*/
@Param(methodName = "postEncryptForm")
public class PostEncryptFormParam extends FormParam {
public PostEncryptFormParam(String url) {
super(url, Method.POST);
}
public PostEncryptFormParam(String url, Method method) {
super(url, method);
}
public PostEncryptFormParam test1(String s) {
return this;
}
//此方法会在
public PostEncryptFormParam test2(long a, float b) {
return this;
}
public int add(int a, int b) {
return a + b;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/param/PostEncryptJsonParam.kt
================================================
package com.example.httpsender.param
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import rxhttp.wrapper.annotation.Param
import rxhttp.wrapper.param.JsonParam
import rxhttp.wrapper.param.Method
import rxhttp.wrapper.utils.GsonUtil
/**
* User: ljx
* Date: 2019/1/25
* Time: 19:32
*/
@Param(methodName = "postEncryptJson")
class PostEncryptJsonParam(url: String) : JsonParam(url, Method.POST) {
private var MEDIA_TYPE_JSON: MediaType = "application/json; charset=utf-8".toMediaType()
/**
* @return 根据自己的业务需求返回对应的RequestBody
*/
override fun getRequestBody(): RequestBody {
//我们要发送Post请求,参数以加密后的json形式发出
//第一步,将参数转换为Json字符串
val json = if (bodyParam == null) "" else GsonUtil.toJson(bodyParam)
//第二步,加密
val encryptByte = encrypt(json, "RxHttp")
//第三部,创建RequestBody并返回
return encryptByte!!.toRequestBody(MEDIA_TYPE_JSON)
}
/**
* @param content 要加密的字符串
* @param password 密码
* @return 加密后的字节数组
*/
private fun encrypt(content: String, password: String): ByteArray? {
//加码代码省略
return null
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/param/PostEncryptJsonParam1.java
================================================
package com.example.httpsender.param;
import okhttp3.RequestBody;
import rxhttp.wrapper.annotation.Param;
import rxhttp.wrapper.param.AbstractBodyParam;
import rxhttp.wrapper.param.Method;
/**
* User: ljx
* Date: 2019-09-11
* Time: 11:52
*/
@Param(methodName = "postEncryptJson1")
public class PostEncryptJsonParam1 extends AbstractBodyParam<PostEncryptJsonParam1> {
public PostEncryptJsonParam1(String url) {
super(url, Method.POST);
}
@Override
public RequestBody getRequestBody() {
return null;
}
public void test() {
}
@Override
public PostEncryptJsonParam1 add(String key, Object value) {
return null;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/parser/Android10DownloadFactory.kt
================================================
package com.example.httpsender.parser
import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.annotation.RequiresApi
import okhttp3.Response
import rxhttp.wrapper.callback.UriFactory
import rxhttp.wrapper.utils.query
import java.io.File
/**
* User: ljx
* Date: 2020/9/11
* Time: 17:43
*
* @param context Context
* @param filename 文件名
* @param relativePath 文件相对路径,可取值:
* [Environment.DIRECTORY_DOWNLOADS]
* [Environment.DIRECTORY_DCIM]
* [Environment.DIRECTORY_PICTURES]
* [Environment.DIRECTORY_MUSIC]
* [Environment.DIRECTORY_MOVIES]
* [Environment.DIRECTORY_DOCUMENTS]
* ...
*/
class Android10DownloadFactory @JvmOverloads constructor(
context: Context,
private val filename: String,
private val relativePath: String = Environment.DIRECTORY_DOWNLOADS
) : UriFactory(context) {
/**
* [MediaStore.Files.getContentUri]
* [MediaStore.Downloads.EXTERNAL_CONTENT_URI]
* [MediaStore.Audio.Media.EXTERNAL_CONTENT_URI]
* [MediaStore.Video.Media.EXTERNAL_CONTENT_URI]
* [MediaStore.Images.Media.EXTERNAL_CONTENT_URI]
*/
@RequiresApi(Build.VERSION_CODES.Q)
fun getInsertUri() = MediaStore.Downloads.EXTERNAL_CONTENT_URI
override fun query(): Uri? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
getInsertUri().query(context, filename, relativePath)
} else {
val file = File("${Environment.getExternalStorageDirectory()}/$relativePath/$filename")
Uri.fromFile(file)
}
}
override fun insert(response: Response): Uri {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val uri = getInsertUri().query(context, filename, relativePath)
/*
* 通过查找,要插入的Uri已经存在,就无需再次插入
* 否则会出现新插入的文件,文件名被系统更改的现象,因为insert不会执行覆盖操作
*/
if (uri != null) return uri
ContentValues().run {
put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath) //下载到指定目录
put(MediaStore.MediaColumns.DISPLAY_NAME, filename) //文件名
//取contentType响应头作为文件类型
put(MediaStore.MediaColumns.MIME_TYPE, response.body?.contentType().toString())
context.contentResolver.insert(getInsertUri(), this)
//当相同路径下的文件,在文件管理器中被手动删除时,就会插入失败
} ?: throw NullPointerException("Uri insert failed. Try changing filename")
} else {
val file = File("${Environment.getExternalStorageDirectory()}/$relativePath/$filename")
Uri.fromFile(file)
}
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/parser/ResponseParser.kt
================================================
package com.example.httpsender.parser
import com.example.httpsender.entity.PageList
import com.example.httpsender.entity.Response
import rxhttp.wrapper.annotation.Parser
import rxhttp.wrapper.exception.ParseException
import rxhttp.wrapper.parse.TypeParser
import rxhttp.wrapper.utils.convertTo
import java.io.IOException
import java.lang.reflect.Type
/**
* 输入T,输出T,并对code统一判断
* User: ljx
* Date: 2018/10/23
* Time: 13:49
*
* 如果使用协程发送请求,wrappers属性可不设置,设置了也无效
*/
@Parser(name = "Response", wrappers = [PageList::class])
open class ResponseParser<T> : TypeParser<T> {
/**
* 此构造方法可适用任意Class对象,但更多用于带泛型的Class对象,如:List<List<Student>>>
*
* 如Java环境中调用
* toObservable(new ResponseParser<List<List<Student>>>(){})
* 等价于kotlin环境下的
* toObservableResponse<List<List<Student>>>()
*
* 注:此构造方法一定要用protected关键字修饰,否则调用此构造方法将拿不到泛型类型
*/
protected constructor() : super()
/**
* 该解析器会生成以下系列方法,前3个kotlin环境调用,后4个Java环境调用,所有方法内部均会调用本构造方法
* toFlowResponse<T>()
* toAwaitResponse<T>()
* toObservableResponse<T>()
* toObservableResponse(Type)
* toObservableResponse(Class<T>)
* toObservableResponseList(Class<T>)
* toObservableResponsePageList(Class<T>)
*
* Flow/Await下 toXxxResponse<PageList<T>> 等同于 toObservableResponsePageList(Class<T>)
*/
constructor(type: Type) : super(type)
@Throws(IOException::class)
override fun onParse(response: okhttp3.Response): T {
val data: Response<T> = response.convertTo(Response::class, *types)
var t = data.data //获取data字段
if (t == null && types[0] === String::class.java) {
/*
* 考虑到有些时候服务端会返回:{"errorCode":0,"errorMsg":"关注成功"} 类似没有data的数据
* 此时code正确,但是data字段为空,直接返回data的话,会报空指针错误,
* 所以,判断泛型为String类型时,重新赋值,并确保赋值不为null
*/
@Suppress("UNCHECKED_CAST")
t = data.msg as T
}
if (data.code != 0 || t == null) { //code不等于0,说明数据不正确,抛出异常
throw ParseException(data.code.toString(), data.msg, response)
}
return t
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/parser/java/DoubleTypeParser.java
================================================
package com.example.httpsender.parser.java;
import android.util.Pair;
import com.example.httpsender.entity.Response;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.lang.reflect.Type;
import rxhttp.wrapper.entity.ParameterizedTypeImpl;
import rxhttp.wrapper.exception.ParseException;
import rxhttp.wrapper.parse.TypeParser;
import rxhttp.wrapper.utils.Converter;
/**
* 大于等于2个泛型的解析器,可以参考此类
* User: ljx
* Date: 2018/10/23
* Time: 13:49
*/
//@Parser(name = "DoubleType")
public class DoubleTypeParser<F, S> extends TypeParser<Pair<F, S>> {
protected DoubleTypeParser() {
super();
}
public DoubleTypeParser(Type fType, Type sType) {
super(fType, sType);
}
@Override
public Pair<F, S> onParse(@NotNull okhttp3.Response response) throws IOException {
Type pairType = ParameterizedTypeImpl.getParameterized(Pair.class, types);
Response<Pair<F, S>> data = Converter.convertTo(response, Response.class, pairType);
Pair<F, S> t = data.getData(); //获取data字段
if (data.getCode() != 0 || t == null) {//code不等于0,说明数据不正确,抛出异常
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/parser/java/ResponseParser.java
================================================
package com.example.httpsender.parser.java;
import com.example.httpsender.entity.Response;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.lang.reflect.Type;
import rxhttp.wrapper.exception.ParseException;
import rxhttp.wrapper.parse.TypeParser;
import rxhttp.wrapper.utils.Converter;
/**
* 输入T,输出T,并对code统一判断
* User: ljx
* Date: 2018/10/23
* Time: 13:49
*/
//@Parser(name = "Response", wrappers = {PageList.class})
public class ResponseParser<T> extends TypeParser<T> {
/**
* 此构造方法可适用任意Class对象,但更多用于带泛型的Class对象,如:List<List<Student>>>
* <p>
* 如Java环境中调用
* toObservable(new ResponseParser<List<List<Student>>>(){})
* 等价与kotlin环境下的
* toObservableResponse<List<List<Student>>>()
* <p>
* 注:此构造方法一定要用protected关键字修饰,否则调用此构造方法将拿不到泛型类型
*/
protected ResponseParser() {
super();
}
/**
* 该解析器会生成以下系列方法,前3个kotlin环境调用,后4个Java环境调用,所有方法内部均会调用本构造方法
* toFlowResponse<T>()
* toAwaitResponse<T>()
* toObservableResponse<T>()
* toObservableResponse(Type)
* toObservableResponse(Class<T>)
* toObservableResponseList(Class<T>)
* toObservableResponsePageList(Class<T>)
* <p>
* Flow/Await下 toXxxResponse<PageList<T>> 等价与 toObservableResponsePageList(Class<T>)
*/
public ResponseParser(Type type) {
super(type);
}
@SuppressWarnings("unchecked")
@Override
public T onParse(@NotNull okhttp3.Response response) throws IOException {
Response<T> data = Converter.convertTo(response, Response.class, types);
T t = data.getData(); //获取data字段
if (t == null && types[0] == String.class) {
/*
* 考虑到有些时候服务端会返回:{"errorCode":0,"errorMsg":"关注成功"} 类似没有data的数据
* 此时code正确,但是data字段为空,直接返回data的话,会报空指针错误,
* 所以,判断泛型为String类型时,重新赋值,并确保赋值不为null
*/
t = (T) data.getMsg();
}
if (data.getCode() != 0 || t == null) {//code不等于0,说明数据不正确,抛出异常
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/utils/Preferences.java
================================================
package com.example.httpsender.utils;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.example.httpsender.AppHolder;
/**
* User: hqs
* Date: 2016/5/10
* Time: 19:07
*/
public class Preferences {
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
private Preferences() {
}
private static SharedPreferences getInstance() {
if (sharedPreferences == null) {
synchronized (Preferences.class) {
if (sharedPreferences == null) {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(AppHolder.getInstance());
}
}
}
return sharedPreferences;
}
public static SharedPreferences.Editor getEditor() {
if (editor == null) {
editor = getInstance().edit();
}
return editor;
}
public static String getValue(String key, String defaultValue) {
return getInstance().getString(key, defaultValue);
}
public static void setValue(String key, String value) {
getEditor().putString(key, value).commit();
}
public static int getValue(String key, int defaultValue) {
return getInstance().getInt(key, defaultValue);
}
public static void setValue(String key, int value) {
getEditor().putInt(key, value).commit();
}
public static void setFloat(String key, float value) {
getEditor().putFloat(key, value).commit();
}
public static float getFloat(String key, float defaultValue) {
return getInstance().getFloat(key, defaultValue);
}
public static boolean getValue(String key, boolean defaultValue) {
return getInstance().getBoolean(key, defaultValue);
}
public static void setValue(String key, boolean value) {
getEditor().putBoolean(key, value).commit();
}
public static long getValue(String key, long defaultValue) {
return getInstance().getLong(key, defaultValue);
}
public static void setValue(String key, long value) {
getEditor().putLong(key, value).commit();
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/view/ScaleTransitionPagerTitleView.java
================================================
package com.example.httpsender.view;
import android.content.Context;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView;
/**
* 带颜色渐变和缩放的指示器标题
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class ScaleTransitionPagerTitleView extends ColorTransitionPagerTitleView {
private float mMinScale = 0.75f;
public ScaleTransitionPagerTitleView(Context context) {
super(context);
}
@Override
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
super.onEnter(index, totalCount, enterPercent, leftToRight); // 实现颜色渐变
setScaleX(mMinScale + (1.0f - mMinScale) * enterPercent);
setScaleY(mMinScale + (1.0f - mMinScale) * enterPercent);
}
@Override
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
super.onLeave(index, totalCount, leavePercent, leftToRight); // 实现颜色渐变
setScaleX(1.0f + (mMinScale - 1.0f) * leavePercent);
setScaleY(1.0f + (mMinScale - 1.0f) * leavePercent);
}
public float getMinScale() {
return mMinScale;
}
public void setMinScale(float minScale) {
mMinScale = minScale;
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/vm/MultiTaskAwaitDownloader.kt
================================================
package com.example.httpsender.vm
import androidx.lifecycle.MutableLiveData
import com.example.httpsender.Tip
import com.example.httpsender.entity.DownloadTask
import com.example.httpsender.utils.Preferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.internal.http2.StreamResetException
import okio.ByteString.Companion.encodeUtf8
import rxhttp.RxHttpPlugins
import rxhttp.awaitResult
import rxhttp.wrapper.param.RxHttp
import java.io.File
import java.util.*
/**
* User: ljx
* Date: 2020/7/12
* Time: 18:00
*/
object MultiTaskAwaitDownloader {
const val IDLE = 0 //未开始,闲置状态
const val WAITING = 1 //等待中状态
const val DOWNLOADING = 2 //下载中
const val PAUSED = 3 //已暂停
const val COMPLETED = 4 //已完成
const val FAIL = 5 //下载失败
const val CANCEL = 6 //取消状态,等待时被取消
private const val MAX_TASK_COUNT = 3 //最大并发数
@JvmStatic
val liveTask = MutableLiveData<DownloadTask>() //用于刷新UI
@JvmStatic
val allTask = ArrayList<DownloadTask>() //所有下载任务
private val waitTask = LinkedList<DownloadTask>() //等待下载的任务
private val downloadingTask = LinkedList<DownloadTask>() //下载中的任务
//记录每个文件的总大小,key为文件url
private val lengthMap = HashMap<String, Long>()
@JvmStatic
fun addTasks(tasks: ArrayList<DownloadTask>) {
val allTaskList = allTask
tasks.forEach {
if (!allTaskList.contains(it)) {
val md5Key = it.url.encodeUtf8().md5().hex()
val length = Preferences.getValue(md5Key, -1L)
if (length != -1L) {
it.totalSize = length
it.currentSize = File(it.localPath).length()
it.progress = it.currentSize * 1.0f / it.totalSize
lengthMap[it.url] = length
if (it.currentSize > 0) {
it.state = PAUSED
}
if (it.totalSize == it.currentSize) {
//如果当前size等于总size,则任务文件下载完成,注意: 这个判断不是100%准确,最好能对文件做md5校验
it.state = COMPLETED
}
}
allTaskList.add(it)
}
}
}
//开始下载所有任务
@JvmStatic
fun startAllDownloadTask() {
val allTaskList = allTask
allTaskList.forEach {
if (it.state != COMPLETED && it.state != DOWNLOADING) {
download(it)
}
}
}
@JvmStatic
fun download(task: DownloadTask) {
if (downloadingTask.size >= MAX_TASK_COUNT) {
//超过最大下载数,添加进等待队列
task.state = WAITING
updateTask(task)
waitTask.offer(task)
return
}
task.state = DOWNLOADING
updateTask(task)
downloadingTask.add(task)
//如果想使用RxJava或Await下载,更改以下代码即可
CoroutineScope(Dispatchers.Main).launch {
// RxHttp.get(task.url)
// .tag(task.url) //记录tag,手动取消下载时用到
// .toDownloadAwait(task.localPath, true) {
// //下载进度回调,0-100,仅在进度有更新时才会回调
// task.progress = it.progress //当前进度 0-100
// task.currentSize = it.currentSize //当前已下载的字节大小
// task.totalSize = it.totalSize //要下载的总字节大小
// updateTask(task)
// val key = task.url
// val length = lengthMap[key]
// if (length != task.totalSize) {
// //服务器返回的文件总大小与本地的不一致,则更新
// lengthMap[key] = task.totalSize
// saveTotalSize(lengthMap)
// }
// }.awaitResult {
// Tip.show("下载成功")
// task.state = COMPLETED
// }.onFailure {
// //手动取消下载时,会收到StreamResetException异常,不做任何处理
// if (it !is StreamResetException) {
// Tip.show("下载失败")
// task.state = FAIL
// }
// }
//下载结束,不管任务成功还是失败,如果还有在等待的任务,都开启下一个任务
updateTask(task)
downloadingTask.remove(task)
waitTask.poll()?.let { download(it) }
}
}
private fun saveTotalSize(map: HashMap<String, Long>) {
val editor = Preferences.getEditor()
for ((key, value) in map) {
val md5Key = key.encodeUtf8().md5().hex()
editor.putLong(md5Key, value)
}
editor.commit()
}
//关闭所有任务
@JvmStatic
fun cancelAllTask() {
var iterator = waitTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
task.state = CANCEL
iterator.remove()
updateTask(task)
}
iterator = downloadingTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
iterator.remove()
RxHttpPlugins.cancelAll(task.url)
task.state = CANCEL
updateTask(task)
}
}
//等待中->取消下载
@JvmStatic
fun removeWaitTask(task: DownloadTask) {
waitTask.remove(task)
task.state = CANCEL
updateTask(task)
}
//暂停下载
@JvmStatic
fun pauseTask(task: DownloadTask) {
//根据tag取消下载
RxHttpPlugins.cancelAll(task.url)
task.state = PAUSED
updateTask(task)
}
@JvmStatic
fun haveTaskExecuting(): Boolean {
return waitTask.size > 0 || downloadingTask.size > 0
}
//发送通知,更新UI
private fun updateTask(task: DownloadTask) {
liveTask.value = task
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/vm/MultiTaskDownloader.kt
================================================
package com.example.httpsender.vm
import android.annotation.SuppressLint
import androidx.lifecycle.MutableLiveData
import com.example.httpsender.Tip
import com.example.httpsender.entity.DownloadTask
import com.example.httpsender.utils.Preferences
import okhttp3.internal.http2.StreamResetException
import okio.ByteString.Companion.encodeUtf8
import rxhttp.RxHttpPlugins
import rxhttp.wrapper.param.RxHttp
import java.io.File
import java.util.*
/**
* User: ljx
* Date: 2020/7/12
* Time: 18:00
*/
object MultiTaskDownloader {
const val IDLE = 0 //未开始,闲置状态
const val WAITING = 1 //等待中状态
const val DOWNLOADING = 2 //下载中
const val PAUSED = 3 //已暂停
const val COMPLETED = 4 //已完成
const val FAIL = 5 //下载失败
const val CANCEL = 6 //取消状态,等待时被取消
private const val MAX_TASK_COUNT = 3 //最大并发数
@JvmStatic
val liveTask = MutableLiveData<DownloadTask>() //用于刷新UI
@JvmStatic
val allTask = ArrayList<DownloadTask>() //所有下载任务
private val waitTask = LinkedList<DownloadTask>() //等待下载的任务
private val downloadingTask = LinkedList<DownloadTask>() //下载中的任务
//记录每个文件的总大小,key为文件url
private val lengthMap = HashMap<String, Long>()
@JvmStatic
fun addTasks(tasks: ArrayList<DownloadTask>) {
val allTaskList = allTask
tasks.forEach {
if (!allTaskList.contains(it)) {
val md5Key = it.url.encodeUtf8().md5().hex()
val length = Preferences.getValue(md5Key, -1L)
if (length != -1L) {
it.totalSize = length
it.currentSize = File(it.localPath).length()
it.progress = it.currentSize * 1.0f / it.totalSize
lengthMap[it.url] = length
if (it.currentSize > 0) {
it.state = PAUSED
}
if (it.totalSize == it.currentSize) {
//如果当前size等于总size,则任务文件下载完成,注意: 这个判断不是100%准确,最好能对文件做md5校验
it.state = COMPLETED
}
}
allTaskList.add(it)
}
}
}
//开始下载所有任务
@JvmStatic
fun startAllDownloadTask() {
val allTaskList = allTask
allTaskList.forEach {
if (it.state != COMPLETED && it.state != DOWNLOADING) {
download(it)
}
}
}
@SuppressLint("CheckResult")
@JvmStatic
fun download(task: DownloadTask) {
if (downloadingTask.size >= MAX_TASK_COUNT) {
//超过最大下载数,添加进等待队列
task.state = WAITING
updateTask(task)
waitTask.offer(task)
return
}
task.state = DOWNLOADING
updateTask(task)
downloadingTask.add(task)
//如果想使用Await或Flow下载,更改以下代码即可
RxHttp.get(task.url)
.tag(task.url) //记录tag,手动取消下载时用到
.toDownloadObservable(task.localPath, true)
.onMainProgress {
//下载进度回调,0-100,仅在进度有更新时才会回调
task.speed = it.speed
task.remainingTime = it.calculateRemainingTime()
task.progress = it.fraction //当前进度 [0.0, 1.0]
task.currentSize = it.currentSize //当前已下载的字节大小
task.totalSize = it.totalSize //要下载的总字节大小
updateTask(task)
val key = task.url
val length = lengthMap[key]
if (length != task.totalSize) {
//服务器返回的文件总大小与本地的不一致,则更新
lengthMap[key] = task.totalSize
saveTotalSize(lengthMap)
}
}
.doFinally {
updateTask(task)
//不管任务成功还是失败,如果还有在等待的任务,都开启下一个任务
downloadingTask.remove(task)
waitTask.poll()?.let { download(it) }
}
.subscribe({
Tip.show("下载完成")
task.state = COMPLETED
}, {
//手动取消下载时,会收到StreamResetException异常,不做任何处理
if (it !is StreamResetException){
Tip.show("下载失败")
task.state = FAIL
}
})
}
private fun saveTotalSize(map: HashMap<String, Long>) {
val editor = Preferences.getEditor()
for ((key, value) in map) {
val md5Key = key.encodeUtf8().md5().hex()
editor.putLong(md5Key, value)
}
editor.commit()
}
//关闭所有任务
@JvmStatic
fun cancelAllTask() {
var iterator = waitTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
task.state = CANCEL
iterator.remove()
updateTask(task)
}
iterator = downloadingTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
iterator.remove()
RxHttpPlugins.cancelAll(task.url)
task.state = CANCEL
updateTask(task)
}
}
//等待中->取消下载
@JvmStatic
fun removeWaitTask(task: DownloadTask) {
waitTask.remove(task)
task.state = CANCEL
updateTask(task)
}
//暂停下载
@JvmStatic
fun pauseTask(task: DownloadTask) {
//根据tag取消下载
RxHttpPlugins.cancelAll(task.url)
task.state = PAUSED
task.speed = 0
task.remainingTime = -1
updateTask(task)
}
@JvmStatic
fun haveTaskExecuting(): Boolean {
return waitTask.size > 0 || downloadingTask.size > 0
}
//发送通知,更新UI
private fun updateTask(task: DownloadTask) {
liveTask.value = task
}
}
================================================
FILE: app/src/main/java/com/example/httpsender/vm/MultiTaskFlowDownloader.kt
================================================
package com.example.httpsender.vm
import androidx.lifecycle.MutableLiveData
import com.example.httpsender.Tip
import com.example.httpsender.entity.DownloadTask
import com.example.httpsender.utils.Preferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import okhttp3.internal.http2.StreamResetException
import okio.ByteString.Companion.encodeUtf8
import rxhttp.RxHttpPlugins
import rxhttp.toDownloadFlow
import rxhttp.wrapper.param.RxHttp
import java.io.File
import java.util.*
/**
* User: ljx
* Date: 2020/7/12
* Time: 18:00
*/
object MultiTaskFlowDownloader {
const val IDLE = 0 //未开始,闲置状态
const val WAITING = 1 //等待中状态
const val DOWNLOADING = 2 //下载中
const val PAUSED = 3 //已暂停
const val COMPLETED = 4 //已完成
const val FAIL = 5 //下载失败
const val CANCEL = 6 //取消状态,等待时被取消
private const val MAX_TASK_COUNT = 3 //最大并发数
@JvmStatic
val liveTask = MutableLiveData<DownloadTask>() //用于刷新UI
@JvmStatic
val allTask = ArrayList<DownloadTask>() //所有下载任务
private val waitTask = LinkedList<DownloadTask>() //等待下载的任务
private val downloadingTask = LinkedList<DownloadTask>() //下载中的任务
//记录每个文件的总大小,key为文件url
private val lengthMap = HashMap<String, Long>()
@JvmStatic
fun addTasks(tasks: ArrayList<DownloadTask>) {
val allTaskList = allTask
tasks.forEach {
if (!allTaskList.contains(it)) {
val md5Key = it.url.encodeUtf8().md5().hex()
val length = Preferences.getValue(md5Key, -1L)
if (length != -1L) {
it.totalSize = length
it.currentSize = File(it.localPath).length()
it.progress = it.currentSize * 1.0f / it.totalSize
lengthMap[it.url] = length
if (it.currentSize > 0) {
it.state = PAUSED
}
if (it.totalSize == it.currentSize) {
//如果当前size等于总size,则任务文件下载完成,注意: 这个判断不是100%准确,最好能对文件做md5校验
it.state = COMPLETED
}
}
allTaskList.add(it)
}
}
}
//开始下载所有任务
@JvmStatic
fun startAllDownloadTask() {
val allTaskList = allTask
allTaskList.forEach {
if (it.state != COMPLETED && it.state != DOWNLOADING) {
download(it)
}
}
}
@JvmStatic
fun download(task: DownloadTask) {
if (downloadingTask.size >= MAX_TASK_COUNT) {
//超过最大下载数,添加进等待队列
task.state = WAITING
updateTask(task)
waitTask.offer(task)
return
}
task.state = DOWNLOADING
updateTask(task)
downloadingTask.add(task)
//如果想使用RxJava或Flow下载,更改以下代码即可
CoroutineScope(Dispatchers.Main).launch {
RxHttp.get(task.url)
.tag(task.url) //记录tag,手动取消下载时用到
.toDownloadFlow(task.localPath, true)
.onProgress{
//下载进度回调,0-100,仅在进度有更新时才会回调
task.progress = it.fraction //当前进度 [0.0, 1.0]
task.currentSize = it.currentSize //当前已下载的字节大小
task.totalSize = it.totalSize //要下载的总字节大小
updateTask(task)
val key = task.url
val length = lengthMap[key]
if (length != task.totalSize) {
//服务器返回的文件总大小与本地的不一致,则更新
lengthMap[key] = task.totalSize
saveTotalSize(lengthMap)
}
}.catch {
//手动取消下载时,会收到StreamResetException异常,不做任何处理
if (it !is StreamResetException) {
Tip.show("下载失败")
task.state = FAIL
}
}.collect {
Tip.show("下载成功")
task.state = COMPLETED
}
//下载结束,不管任务成功还是失败,如果还有在等待的任务,都开启下一个任务
updateTask(task)
downloadingTask.remove(task)
waitTask.poll()?.let { download(it) }
}
}
private fun saveTotalSize(map: HashMap<String, Long>) {
val editor = Preferences.getEditor()
for ((key, value) in map) {
val md5Key = key.encodeUtf8().md5().hex()
editor.putLong(md5Key, value)
}
editor.commit()
}
//关闭所有任务
@JvmStatic
fun cancelAllTask() {
var iterator = waitTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
task.state = CANCEL
iterator.remove()
updateTask(task)
}
iterator = downloadingTask.iterator()
while (iterator.hasNext()) {
val task = iterator.next()
iterator.remove()
RxHttpPlugins.cancelAll(task.url)
task.state = CANCEL
updateTask(task)
}
}
//等待中->取消下载
@JvmStatic
fun removeWaitTask(task: DownloadTask) {
waitTask.remove(task)
task.state = CANCEL
updateTask(task)
}
//暂停下载
@JvmStatic
fun pauseTask(task: DownloadTask) {
//根据tag取消下载
RxHttpPlugins.cancelAll(task.url)
task.state = PAUSED
updateTask(task)
}
@JvmStatic
fun haveTaskExecuting(): Boolean {
return waitTask.size > 0 || downloadingTask.size > 0
}
//发送通知,更新UI
private fun updateTask(task: DownloadTask) {
liveTask.value = task
}
}
================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
================================================
FILE: app/src/main/res/layout/await_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="click"
type="android.view.View.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="10dp"
android:paddingTop="20dp"
android:paddingEnd="10dp"
android:paddingBottom="20dp"
tools:context=".MainActivity">
<ScrollView
android:id="@+id/left_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/ll_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/sendGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get请求"
android:onClick="@{v->click.onClick(v)}"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostForm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送表单请求"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostJson"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送json对象"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostJsonArray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送json数组"
android:textAllCaps="false" />
<Button
android:id="@+id/xmlConverter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送/接收 xml数据"
android:textAllCaps="false" />
<Button
android:id="@+id/upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件上传"
android:textAllCaps="false" />
<Button
android:id="@+id/upload10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="Android 10 文件上传"
android:textAllCaps="false" />
<Button
android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件下载"
android:textAllCaps="false" />
<Button
android:id="@+id/download_append"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件断点下载"
android:textAllCaps="false" />
<Button
android:id="@+id/download10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="Android 10 文件下载"
android:textAllCaps="false" />
<Button
android:id="@+id/download10_append"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="Android 10 断点下载"
android:textAllCaps="false" />
</LinearLayout>
</ScrollView>
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:background="#CCCCCC"
app:layout_constraintBottom_toTopOf="@+id/bt_clear"
app:layout_constraintLeft_toRightOf="@+id/left_scroll_view"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/left_scroll_view">
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:scrollbars="vertical"
android:textColor="@android:color/black" />
</ScrollView>
<Button
android:id="@+id/bt_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:onClick="@{v->click.onClick(v)}"
android:text="清空日志"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
================================================
FILE: app/src/main/res/layout/download_multi_adapter.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="1dp"
android:background="@android:color/white"
android:gravity="center">
<TextView
android:id="@+id/tv_waiting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="等待中..."
app:layout_constraintBottom_toTopOf="@+id/progress_bar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:max="100"
app:layout_constraintBottom_toTopOf="@+id/tv_progress"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bt_pause"
app:layout_constraintTop_toBottomOf="@+id/tv_waiting" />
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progress_bar" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBaseline_toBaselineOf="@+id/tv_progress"
app:layout_constraintRight_toRightOf="@+id/progress_bar" />
<Button
android:id="@+id/bt_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:text="开始"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/progress_bar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
================================================
FILE: app/src/main/res/layout/flow_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="click"
type="android.view.View.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="10dp"
android:paddingTop="20dp"
android:paddingEnd="10dp"
android:paddingBottom="20dp"
tools:context=".MainActivity">
<ScrollView
android:id="@+id/left_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/ll_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/sendGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get请求"
android:onClick="@{v->click.onClick(v)}"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostForm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送表单请求"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostJson"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送json对象"
android:textAllCaps="false" />
<Button
android:id="@+id/sendPostJsonArray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送json数组"
android:textAllCaps="false" />
<Button
android:id="@+id/xmlConverter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="发送/接收 xml数据"
android:textAllCaps="false" />
<Button
android:id="@+id/upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件上传"
android:textAllCaps="false" />
<Button
android:id="@+id/upload10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="Android 10 文件上传"
android:textAllCaps="false" />
<Button
android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件下载"
android:textAllCaps="false" />
<Button
android:id="@+id/download_append"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="文件断点下载"
android:textAllCaps="false" />
<Button
android:id="@+id/download10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v->click.onClick(v)}"
android:text="Android 10 文件下载"
android:
gitextract_l14p6_sk/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_zh.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── example/ │ │ └── httpsender/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── httpsender/ │ │ │ ├── AppHolder.java │ │ │ ├── DownloadMultiAdapter.java │ │ │ ├── ExceptionHelper.java │ │ │ ├── LoggingEventListener.kt │ │ │ ├── MainActivity.java │ │ │ ├── MyViewModel.kt │ │ │ ├── OnError.java │ │ │ ├── Presenter.kt │ │ │ ├── RxHttpManager.java │ │ │ ├── Tip.java │ │ │ ├── ToolBarActivity.java │ │ │ ├── adapter/ │ │ │ │ └── FragmentPageAdapter.java │ │ │ ├── entity/ │ │ │ │ ├── Article.java │ │ │ │ ├── DownloadTask.java │ │ │ │ ├── ErrorInfo.java │ │ │ │ ├── Location.java │ │ │ │ ├── Name.java │ │ │ │ ├── NewsDataXml.java │ │ │ │ ├── NewsXml.java │ │ │ │ ├── PageList.java │ │ │ │ ├── Response.java │ │ │ │ ├── Url.kt │ │ │ │ └── User.java │ │ │ ├── fragment/ │ │ │ │ ├── AwaitFragment.kt │ │ │ │ ├── BaseFragment.kt │ │ │ │ ├── FlowFragment.kt │ │ │ │ ├── MultiDownloadFragment.java │ │ │ │ └── RxJavaFragment.kt │ │ │ ├── interceptor/ │ │ │ │ ├── RedirectInterceptor.java │ │ │ │ └── TokenInterceptor.java │ │ │ ├── kt/ │ │ │ │ ├── Activity.kt │ │ │ │ ├── KotlinExtensions.kt │ │ │ │ └── Uri.kt │ │ │ ├── param/ │ │ │ │ ├── GetEncryptParam.java │ │ │ │ ├── PostEncryptFormParam.java │ │ │ │ ├── PostEncryptJsonParam.kt │ │ │ │ └── PostEncryptJsonParam1.java │ │ │ ├── parser/ │ │ │ │ ├── Android10DownloadFactory.kt │ │ │ │ ├── ResponseParser.kt │ │ │ │ └── java/ │ │ │ │ ├── DoubleTypeParser.java │ │ │ │ └── ResponseParser.java │ │ │ ├── utils/ │ │ │ │ └── Preferences.java │ │ │ ├── view/ │ │ │ │ └── ScaleTransitionPagerTitleView.java │ │ │ └── vm/ │ │ │ ├── MultiTaskAwaitDownloader.kt │ │ │ ├── MultiTaskDownloader.kt │ │ │ └── MultiTaskFlowDownloader.kt │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ ├── await_fragment.xml │ │ │ ├── download_multi_adapter.xml │ │ │ ├── flow_fragment.xml │ │ │ ├── main_activity.xml │ │ │ ├── multi_download_fragment.xml │ │ │ ├── rxjava_fragment.xml │ │ │ └── toolbar_activity.xml │ │ ├── menu/ │ │ │ └── download.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── values/ │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ ├── styles.xml │ │ │ └── themes.xml │ │ └── xml/ │ │ └── network_config.xml │ └── test/ │ └── java/ │ ├── com/ │ │ └── rxhttp/ │ │ └── compiler/ │ │ ├── AbstractTestSymbolProcessor.kt │ │ ├── KspProcessorTest.kt │ │ ├── TestParser1.kt │ │ └── TestParser2.kt │ └── com.example.httpsender/ │ └── AsyncTest.java ├── build.gradle ├── gradle/ │ ├── libs.versions.toml │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── jitpack.yml ├── maven.gradle ├── maven_dependency.md ├── rxhttp/ │ ├── build.gradle │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── rxhttp/ │ │ │ ├── AwaitTransform.kt │ │ │ ├── CallFactoryExt.kt │ │ │ ├── Platform.java │ │ │ ├── RxHttpPlugins.java │ │ │ └── wrapper/ │ │ │ ├── CallFactory.kt │ │ │ ├── OkHttpCompat.java │ │ │ ├── cache/ │ │ │ │ ├── CacheManager.java │ │ │ │ ├── CacheMode.java │ │ │ │ ├── CacheStrategy.java │ │ │ │ ├── HeadersVary.java │ │ │ │ └── InternalCache.java │ │ │ ├── callback/ │ │ │ │ ├── Consumer.java │ │ │ │ ├── Function.java │ │ │ │ ├── IConverter.java │ │ │ │ ├── JsonConverter.java │ │ │ │ ├── OutputStreamFactory.kt │ │ │ │ ├── ProgressCallback.java │ │ │ │ └── ProgressCallbackHelper.kt │ │ │ ├── converter/ │ │ │ │ └── GsonConverter.java │ │ │ ├── cookie/ │ │ │ │ ├── CookieStore.java │ │ │ │ └── ICookieJar.java │ │ │ ├── coroutines/ │ │ │ │ ├── Await.kt │ │ │ │ ├── CallAwait.kt │ │ │ │ └── CallFlow.kt │ │ │ ├── entity/ │ │ │ │ ├── DownloadOffSize.java │ │ │ │ ├── EmptyResponseBody.java │ │ │ │ ├── ExpandOutputStream.java │ │ │ │ ├── FileRequestBody.java │ │ │ │ ├── KeyValuePair.java │ │ │ │ ├── OkResponse.java │ │ │ │ ├── ParameterizedTypeImpl.java │ │ │ │ ├── Progress.java │ │ │ │ ├── UpFile.java │ │ │ │ └── UriRequestBody.java │ │ │ ├── exception/ │ │ │ │ ├── CacheReadFailedException.java │ │ │ │ ├── HttpStatusCodeException.java │ │ │ │ ├── ParseException.java │ │ │ │ └── ProxyException.java │ │ │ ├── intercept/ │ │ │ │ ├── CacheInterceptor.kt │ │ │ │ ├── LogInterceptor.kt │ │ │ │ └── RangeInterceptor.java │ │ │ ├── param/ │ │ │ │ ├── AbstractBodyParam.java │ │ │ │ ├── AbstractParam.java │ │ │ │ ├── BodyParam.kt │ │ │ │ ├── FormParam.java │ │ │ │ ├── ICache.java │ │ │ │ ├── IHeaders.java │ │ │ │ ├── IParam.java │ │ │ │ ├── IPart.java │ │ │ │ ├── IRequest.java │ │ │ │ ├── JsonArrayParam.java │ │ │ │ ├── JsonParam.java │ │ │ │ ├── Method.java │ │ │ │ ├── NoBodyParam.java │ │ │ │ └── Param.java │ │ │ ├── parse/ │ │ │ │ ├── OkResponseParser.java │ │ │ │ ├── Parser.java │ │ │ │ ├── SmartParser.java │ │ │ │ ├── StreamParser.kt │ │ │ │ └── TypeParser.java │ │ │ ├── progress/ │ │ │ │ └── ProgressRequestBody.java │ │ │ ├── ssl/ │ │ │ │ └── HttpsUtils.java │ │ │ └── utils/ │ │ │ ├── BuildUtil.java │ │ │ ├── CacheUtil.java │ │ │ ├── Converter.java │ │ │ ├── Converter.kt │ │ │ ├── GsonUtil.java │ │ │ ├── JSONStringer.java │ │ │ ├── Json.kt │ │ │ ├── LogTime.java │ │ │ ├── LogUtil.java │ │ │ ├── PathEncoder.kt │ │ │ ├── Speeder.kt │ │ │ ├── TypeUtil.java │ │ │ ├── Uri.kt │ │ │ └── Utils.kt │ │ └── java-templates/ │ │ └── rxhttp/ │ │ └── internal/ │ │ └── RxHttpVersion.kt │ └── test/ │ └── java/ │ └── rxhttp/ │ └── wrapper/ │ └── entity/ │ └── ParameterizedTypeImplTest.java ├── rxhttp-annotation/ │ ├── build.gradle │ └── src/ │ └── main/ │ └── java/ │ └── rxhttp/ │ └── wrapper/ │ └── annotation/ │ ├── Converter.java │ ├── DefaultDomain.java │ ├── Domain.java │ ├── OkClient.java │ ├── Param.java │ └── Parser.java ├── rxhttp-compiler/ │ ├── build.gradle │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── rxhttp/ │ │ └── compiler/ │ │ ├── Constants.kt │ │ ├── KaptProcessor.kt │ │ ├── KspProcessor.kt │ │ ├── RxJavaVersion.kt │ │ ├── Variables.kt │ │ ├── common/ │ │ │ ├── KtUtil.kt │ │ │ ├── ObservableUtil.kt │ │ │ └── StringUtil.kt │ │ ├── kapt/ │ │ │ ├── BaseRxHttpGenerator.kt │ │ │ ├── ClassHelper.kt │ │ │ ├── ConverterVisitor.kt │ │ │ ├── DefaultDomainVisitor.kt │ │ │ ├── DomainVisitor.kt │ │ │ ├── OkClientVisitor.kt │ │ │ ├── ParamsVisitor.kt │ │ │ ├── ParserVisitor.kt │ │ │ ├── RxHttpExtensions.kt │ │ │ ├── RxHttpGenerator.kt │ │ │ ├── RxHttpWrapper.kt │ │ │ ├── Utils.kt │ │ │ └── maven/ │ │ │ ├── KaptRxJava2Processor.kt │ │ │ └── KaptRxJava3Processor.kt │ │ └── ksp/ │ │ ├── BaseRxHttpGenerator.kt │ │ ├── ClassHelper.kt │ │ ├── ConverterVisitor.kt │ │ ├── DefaultDomainVisitor.kt │ │ ├── DomainVisitor.kt │ │ ├── KClassHelper.kt │ │ ├── Ksp.kt │ │ ├── OkClientVisitor.kt │ │ ├── ParamsVisitor.kt │ │ ├── ParserVisitor.kt │ │ ├── RxHttpExtensions.kt │ │ ├── RxHttpGenerator.kt │ │ └── RxHttpWrapper.kt │ └── resources/ │ └── META-INF/ │ ├── gradle/ │ │ └── incremental.annotation.processors │ └── services/ │ ├── com.google.devtools.ksp.processing.SymbolProcessorProvider │ └── javax.annotation.processing.Processor ├── rxhttp-converter/ │ ├── converter-fastjson/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── rxhttp/ │ │ └── wrapper/ │ │ └── converter/ │ │ └── FastJsonConverter.java │ ├── converter-jackson/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── rxhttp/ │ │ └── wrapper/ │ │ └── converter/ │ │ └── JacksonConverter.java │ ├── converter-moshi/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── rxhttp/ │ │ └── wrapper/ │ │ └── converter/ │ │ └── MoshiConverter.java │ ├── converter-protobuf/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── rxhttp/ │ │ └── wrapper/ │ │ └── converter/ │ │ └── ProtoConverter.java │ ├── converter-serialization/ │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── rxhttp/ │ │ └── wrapper/ │ │ └── converter/ │ │ └── SerializationConverter.kt │ └── converter-simplexml/ │ ├── .gitignore │ ├── build.gradle │ └── src/ │ └── main/ │ └── java/ │ └── rxhttp/ │ └── wrapper/ │ └── converter/ │ └── XmlConverter.java └── settings.gradle
SYMBOL INDEX (859 symbols across 95 files)
FILE: app/src/androidTest/java/com/example/httpsender/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 21) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 23) | @Test
FILE: app/src/main/java/com/example/httpsender/AppHolder.java
class AppHolder (line 14) | public class AppHolder extends Application {
method getInstance (line 18) | public static AppHolder getInstance() {
method onCreate (line 22) | @Override
method attachBaseContext (line 29) | protected void attachBaseContext(Context base) {
FILE: app/src/main/java/com/example/httpsender/DownloadMultiAdapter.java
class DownloadMultiAdapter (line 27) | public class DownloadMultiAdapter extends RecyclerView.Adapter<MyViewHol...
method DownloadMultiAdapter (line 33) | public DownloadMultiAdapter(List<DownloadTask> downloadTasks) {
method onCreateViewHolder (line 37) | @NonNull
method onBindViewHolder (line 44) | @SuppressLint("DefaultLocale")
method getSpeed (line 86) | private String getSpeed(long speed) {
method getRemainingTime (line 95) | private String getRemainingTime(long time) {
method getItemCount (line 105) | @Override
method getItemId (line 110) | @Override
class MyViewHolder (line 115) | static class MyViewHolder extends RecyclerView.ViewHolder {
method MyViewHolder (line 124) | MyViewHolder(@NonNull View itemView) {
method setOnItemClickListener (line 135) | public void setOnItemClickListener(OnItemClickListener<DownloadTask> o...
type OnItemClickListener (line 139) | public interface OnItemClickListener<T> {
method onItemClick (line 140) | void onItemClick(View view, T data, int position);
FILE: app/src/main/java/com/example/httpsender/ExceptionHelper.java
class ExceptionHelper (line 14) | public class ExceptionHelper {
method isNetworkConnected (line 16) | @SuppressWarnings("deprecation")
FILE: app/src/main/java/com/example/httpsender/MainActivity.java
class MainActivity (line 42) | public class MainActivity extends AppCompatActivity {
method onCreate (line 48) | @Override
method initMagicIndicator (line 79) | public void initMagicIndicator() {
method dp2px (line 118) | private int dp2px(double dpValue) {
FILE: app/src/main/java/com/example/httpsender/OnError.java
type OnError (line 15) | public interface OnError extends Consumer<Throwable> {
method accept (line 17) | @Override
method onError (line 22) | void onError(ErrorInfo error) throws Exception;
FILE: app/src/main/java/com/example/httpsender/RxHttpManager.java
class RxHttpManager (line 27) | public class RxHttpManager {
method init (line 38) | public static void init(Application context) {
FILE: app/src/main/java/com/example/httpsender/Tip.java
class Tip (line 14) | public class Tip {
method show (line 19) | public static void show(int msgResId) {
method show (line 23) | public static void show(int msgResId, boolean timeLong) {
method show (line 27) | public static void show(CharSequence msg) {
method show (line 31) | public static void show(final CharSequence msg, final boolean timeLong) {
method runOnUiThread (line 42) | private static void runOnUiThread(Runnable runnable) {
FILE: app/src/main/java/com/example/httpsender/ToolBarActivity.java
class ToolBarActivity (line 18) | public abstract class ToolBarActivity extends AppCompatActivity {
method bindingInflate (line 24) | public <T extends ViewDataBinding> T bindingInflate(@LayoutRes int lay...
method setContentView (line 29) | @Override
method initView (line 35) | private void initView() {
method onOptionsItemSelected (line 46) | @Override
method setToolbarColor (line 57) | public void setToolbarColor(int color) {
method setTitle (line 64) | @Override
method setTitle (line 71) | @Override
method dp2px (line 78) | protected int dp2px(float dpValue) {
FILE: app/src/main/java/com/example/httpsender/adapter/FragmentPageAdapter.java
class FragmentPageAdapter (line 18) | public class FragmentPageAdapter extends FragmentPagerAdapter {
method FragmentPageAdapter (line 24) | public FragmentPageAdapter(FragmentManager fm, List<? extends Fragment...
method FragmentPageAdapter (line 28) | public FragmentPageAdapter(FragmentManager fm, List<? extends Fragment...
method getCount (line 34) | @Override
method getPageTitle (line 39) | @Override
method getItem (line 44) | @Override
FILE: app/src/main/java/com/example/httpsender/entity/Article.java
class Article (line 9) | public class Article {
method getApkLink (line 71) | public String getApkLink() {
method getAudit (line 75) | public int getAudit() {
method getAuthor (line 79) | public String getAuthor() {
method getChapterId (line 83) | public int getChapterId() {
method getChapterName (line 87) | public String getChapterName() {
method isCollect (line 91) | public boolean isCollect() {
method getCourseId (line 95) | public int getCourseId() {
method getDesc (line 99) | public String getDesc() {
method getEnvelopePic (line 103) | public String getEnvelopePic() {
method isFresh (line 107) | public boolean isFresh() {
method getId (line 111) | public int getId() {
method getLink (line 115) | public String getLink() {
method getNiceDate (line 119) | public String getNiceDate() {
method getNiceShareDate (line 123) | public String getNiceShareDate() {
method getOrigin (line 127) | public String getOrigin() {
method getPrefix (line 131) | public String getPrefix() {
method getProjectLink (line 135) | public String getProjectLink() {
method getPublishTime (line 139) | public long getPublishTime() {
method getShareDate (line 143) | public long getShareDate() {
method getShareUser (line 147) | public String getShareUser() {
method getSuperChapterId (line 151) | public int getSuperChapterId() {
method getSuperChapterName (line 155) | public String getSuperChapterName() {
method getTitle (line 159) | public String getTitle() {
method getType (line 163) | public int getType() {
method getUserId (line 167) | public int getUserId() {
method getVisible (line 171) | public int getVisible() {
method getZan (line 175) | public int getZan() {
method setApkLink (line 180) | public void setApkLink(String apkLink) {
method setAudit (line 184) | public void setAudit(int audit) {
method setAuthor (line 188) | public void setAuthor(String author) {
method setChapterId (line 192) | public void setChapterId(int chapterId) {
method setChapterName (line 196) | public void setChapterName(String chapterName) {
method setCollect (line 200) | public void setCollect(boolean collect) {
method setCourseId (line 204) | public void setCourseId(int courseId) {
method setDesc (line 208) | public void setDesc(String desc) {
method setEnvelopePic (line 212) | public void setEnvelopePic(String envelopePic) {
method setFresh (line 216) | public void setFresh(boolean fresh) {
method setId (line 220) | public void setId(int id) {
method setLink (line 224) | public void setLink(String link) {
method setNiceDate (line 228) | public void setNiceDate(String niceDate) {
method setNiceShareDate (line 232) | public void setNiceShareDate(String niceShareDate) {
method setOrigin (line 236) | public void setOrigin(String origin) {
method setPrefix (line 240) | public void setPrefix(String prefix) {
method setProjectLink (line 244) | public void setProjectLink(String projectLink) {
method setPublishTime (line 248) | public void setPublishTime(long publishTime) {
method setShareDate (line 252) | public void setShareDate(long shareDate) {
method setShareUser (line 256) | public void setShareUser(String shareUser) {
method setSuperChapterId (line 260) | public void setSuperChapterId(int superChapterId) {
method setSuperChapterName (line 264) | public void setSuperChapterName(String superChapterName) {
method setTitle (line 268) | public void setTitle(String title) {
method setType (line 272) | public void setType(int type) {
method setUserId (line 276) | public void setUserId(int userId) {
method setVisible (line 280) | public void setVisible(int visible) {
method setZan (line 284) | public void setZan(int zan) {
method equals (line 289) | @Override
method hashCode (line 299) | @Override
FILE: app/src/main/java/com/example/httpsender/entity/DownloadTask.java
class DownloadTask (line 10) | public class DownloadTask {
method DownloadTask (line 25) | public DownloadTask(String url) {
method getState (line 29) | public int getState() {
method setState (line 33) | public void setState(int state) {
method getUrl (line 37) | public String getUrl() {
method setUrl (line 41) | public void setUrl(String url) {
method getLocalPath (line 45) | public String getLocalPath() {
method setLocalPath (line 49) | public void setLocalPath(String localPath) {
method getSpeed (line 53) | public long getSpeed() {
method setSpeed (line 57) | public void setSpeed(long speed) {
method getRemainingTime (line 61) | public long getRemainingTime() {
method setRemainingTime (line 65) | public void setRemainingTime(long remainingTime) {
method getProgress (line 69) | public float getProgress() {
method setProgress (line 73) | public void setProgress(float progress) {
method getCurrentSize (line 77) | public long getCurrentSize() {
method setCurrentSize (line 81) | public void setCurrentSize(long currentSize) {
method getTotalSize (line 85) | public long getTotalSize() {
method setTotalSize (line 89) | public void setTotalSize(long totalSize) {
method equals (line 93) | @Override
method hashCode (line 103) | @Override
FILE: app/src/main/java/com/example/httpsender/entity/ErrorInfo.java
class ErrorInfo (line 25) | public class ErrorInfo {
method ErrorInfo (line 31) | public ErrorInfo(Throwable throwable) {
method getErrorCode (line 65) | public int getErrorCode() {
method getErrorMsg (line 69) | public String getErrorMsg() {
method getThrowable (line 73) | public Throwable getThrowable() {
method show (line 77) | public boolean show() {
method show (line 85) | public boolean show(String standbyMsg) {
method show (line 93) | public boolean show(int standbyMsg) {
method getString (line 98) | public String getString(int resId) {
FILE: app/src/main/java/com/example/httpsender/entity/Location.java
class Location (line 8) | public class Location {
method Location (line 13) | public Location(double longitude, double latitude) {
method getLongitude (line 18) | public double getLongitude() {
method getLatitude (line 22) | public double getLatitude() {
FILE: app/src/main/java/com/example/httpsender/entity/Name.java
class Name (line 8) | public class Name {
method Name (line 12) | public Name(String name) {
method getName (line 16) | public String getName() {
method setName (line 20) | public void setName(String name) {
FILE: app/src/main/java/com/example/httpsender/entity/NewsDataXml.java
class NewsDataXml (line 15) | @Root(name = "body", strict = false) //name:要解析的xml数据的头部
FILE: app/src/main/java/com/example/httpsender/entity/NewsXml.java
class NewsXml (line 11) | @Root(name = "route", strict = false) //要解析的xml数据的头部
FILE: app/src/main/java/com/example/httpsender/entity/PageList.java
class PageList (line 12) | public class PageList<T> {
method getCurPage (line 19) | public int getCurPage() {
method getPageCount (line 23) | public int getPageCount() {
method getTotal (line 27) | public int getTotal() {
method getDatas (line 31) | public List<T> getDatas() {
method setCurPage (line 35) | public void setCurPage(int curPage) {
method setPageCount (line 39) | public void setPageCount(int pageCount) {
method setTotal (line 43) | public void setTotal(int total) {
method setDatas (line 47) | public void setDatas(ArrayList<T> datas) {
FILE: app/src/main/java/com/example/httpsender/entity/Response.java
class Response (line 9) | public class Response<T> {
method getCode (line 15) | public int getCode() {
method getMsg (line 19) | public String getMsg() {
method getData (line 23) | public T getData() {
method setErrorCode (line 27) | public void setErrorCode(int errorCode) {
method setErrorMsg (line 31) | public void setErrorMsg(String errorMsg) {
method setData (line 35) | public void setData(T data) {
FILE: app/src/main/java/com/example/httpsender/entity/User.java
class User (line 8) | public class User {
method get (line 14) | public static User get() {
method getToken (line 24) | public String getToken() {
method setToken (line 28) | public void setToken(String token) {
FILE: app/src/main/java/com/example/httpsender/fragment/MultiDownloadFragment.java
class MultiDownloadFragment (line 28) | public class MultiDownloadFragment extends BaseFragment<MultiDownloadFra...
method onCreate (line 80) | @Override
method onViewCreated (line 86) | @Override
method onClick (line 115) | @Override
method onItemClick (line 125) | @Override
FILE: app/src/main/java/com/example/httpsender/interceptor/RedirectInterceptor.java
class RedirectInterceptor (line 15) | public class RedirectInterceptor implements Interceptor {
method intercept (line 17) | @Override
FILE: app/src/main/java/com/example/httpsender/interceptor/TokenInterceptor.java
class TokenInterceptor (line 22) | public class TokenInterceptor implements Interceptor {
method intercept (line 28) | @NotNull
method handleTokenInvalid (line 42) | private Response handleTokenInvalid(Chain chain, Request request) thro...
method refreshToken (line 56) | private boolean refreshToken() {
FILE: app/src/main/java/com/example/httpsender/param/GetEncryptParam.java
class GetEncryptParam (line 21) | @Param(methodName = "getEncrypt")
method GetEncryptParam (line 24) | public GetEncryptParam(String url) {
method test (line 28) | @SafeVarargs
method getHttpUrl (line 33) | @Override
FILE: app/src/main/java/com/example/httpsender/param/PostEncryptFormParam.java
class PostEncryptFormParam (line 14) | @Param(methodName = "postEncryptForm")
method PostEncryptFormParam (line 17) | public PostEncryptFormParam(String url) {
method PostEncryptFormParam (line 21) | public PostEncryptFormParam(String url, Method method) {
method test1 (line 25) | public PostEncryptFormParam test1(String s) {
method test2 (line 30) | public PostEncryptFormParam test2(long a, float b) {
method add (line 34) | public int add(int a, int b) {
FILE: app/src/main/java/com/example/httpsender/param/PostEncryptJsonParam1.java
class PostEncryptJsonParam1 (line 13) | @Param(methodName = "postEncryptJson1")
method PostEncryptJsonParam1 (line 16) | public PostEncryptJsonParam1(String url) {
method getRequestBody (line 20) | @Override
method test (line 25) | public void test() {
method add (line 29) | @Override
FILE: app/src/main/java/com/example/httpsender/parser/java/DoubleTypeParser.java
class DoubleTypeParser (line 24) | public class DoubleTypeParser<F, S> extends TypeParser<Pair<F, S>> {
method DoubleTypeParser (line 26) | protected DoubleTypeParser() {
method DoubleTypeParser (line 30) | public DoubleTypeParser(Type fType, Type sType) {
method onParse (line 34) | @Override
FILE: app/src/main/java/com/example/httpsender/parser/java/ResponseParser.java
class ResponseParser (line 21) | public class ResponseParser<T> extends TypeParser<T> {
method ResponseParser (line 33) | protected ResponseParser() {
method ResponseParser (line 49) | public ResponseParser(Type type) {
method onParse (line 53) | @SuppressWarnings("unchecked")
FILE: app/src/main/java/com/example/httpsender/utils/Preferences.java
class Preferences (line 14) | public class Preferences {
method Preferences (line 19) | private Preferences() {
method getInstance (line 22) | private static SharedPreferences getInstance() {
method getEditor (line 33) | public static SharedPreferences.Editor getEditor() {
method getValue (line 40) | public static String getValue(String key, String defaultValue) {
method setValue (line 44) | public static void setValue(String key, String value) {
method getValue (line 48) | public static int getValue(String key, int defaultValue) {
method setValue (line 52) | public static void setValue(String key, int value) {
method setFloat (line 56) | public static void setFloat(String key, float value) {
method getFloat (line 60) | public static float getFloat(String key, float defaultValue) {
method getValue (line 64) | public static boolean getValue(String key, boolean defaultValue) {
method setValue (line 68) | public static void setValue(String key, boolean value) {
method getValue (line 72) | public static long getValue(String key, long defaultValue) {
method setValue (line 76) | public static void setValue(String key, long value) {
FILE: app/src/main/java/com/example/httpsender/view/ScaleTransitionPagerTitleView.java
class ScaleTransitionPagerTitleView (line 12) | public class ScaleTransitionPagerTitleView extends ColorTransitionPagerT...
method ScaleTransitionPagerTitleView (line 15) | public ScaleTransitionPagerTitleView(Context context) {
method onEnter (line 19) | @Override
method onLeave (line 26) | @Override
method getMinScale (line 33) | public float getMinScale() {
method setMinScale (line 37) | public void setMinScale(float minScale) {
FILE: app/src/test/java/com.example.httpsender/AsyncTest.java
class AsyncTest (line 35) | public class AsyncTest {
method setUp (line 41) | @Before
method success (line 49) | @Test
method successList (line 68) | @Test
method successOKResponse (line 83) | @Test
method failure (line 100) | @Test
FILE: rxhttp-converter/converter-fastjson/src/main/java/rxhttp/wrapper/converter/FastJsonConverter.java
class FastJsonConverter (line 23) | public class FastJsonConverter implements JsonConverter {
method FastJsonConverter (line 29) | private FastJsonConverter(ParserConfig parserConfig, SerializeConfig s...
method create (line 35) | public static FastJsonConverter create() {
method create (line 39) | public static FastJsonConverter create(ParserConfig parserConfig) {
method create (line 43) | public static FastJsonConverter create(SerializeConfig serializeConfig) {
method create (line 47) | public static FastJsonConverter create(ParserConfig parserConfig, Seri...
method create (line 51) | public static FastJsonConverter create(ParserConfig parserConfig, Seri...
method convert (line 57) | @NotNull
method convert (line 79) | @SuppressWarnings("deprecation")
FILE: rxhttp-converter/converter-jackson/src/main/java/rxhttp/wrapper/converter/JacksonConverter.java
class JacksonConverter (line 24) | public class JacksonConverter implements JsonConverter {
method JacksonConverter (line 29) | private JacksonConverter(ObjectMapper mapper, MediaType contentType) {
method create (line 34) | public static JacksonConverter create() {
method create (line 38) | public static JacksonConverter create(ObjectMapper mapper) {
method create (line 42) | public static JacksonConverter create(ObjectMapper mapper, MediaType c...
method convert (line 47) | @NotNull
method convert (line 71) | @SuppressWarnings("deprecation")
FILE: rxhttp-converter/converter-moshi/src/main/java/rxhttp/wrapper/converter/MoshiConverter.java
class MoshiConverter (line 30) | public class MoshiConverter implements JsonConverter {
method MoshiConverter (line 40) | private MoshiConverter(Moshi moshi, boolean lenient, boolean failOnUnk...
method create (line 53) | public static MoshiConverter create() {
method create (line 63) | public static MoshiConverter create(Moshi moshi) {
method create (line 73) | public static MoshiConverter create(Moshi moshi, MediaType contentType) {
method asLenient (line 83) | public MoshiConverter asLenient() {
method failOnUnknown (line 92) | public MoshiConverter failOnUnknown() {
method withNullSerialization (line 101) | public MoshiConverter withNullSerialization() {
method convert (line 105) | @NotNull
method convert (line 152) | @SuppressWarnings({"unchecked", "deprecation"})
FILE: rxhttp-converter/converter-protobuf/src/main/java/rxhttp/wrapper/converter/ProtoConverter.java
class ProtoConverter (line 26) | public class ProtoConverter implements IConverter {
method ProtoConverter (line 31) | public ProtoConverter() {
method ProtoConverter (line 35) | public ProtoConverter(ExtensionRegistryLite registry) {
method ProtoConverter (line 39) | public ProtoConverter(ExtensionRegistryLite registry, MediaType conten...
method convert (line 44) | @NotNull
method convert (line 70) | @SuppressWarnings("deprecation")
method getParser (line 79) | private static Parser<MessageLite> getParser(Class<?> c) {
FILE: rxhttp-converter/converter-simplexml/src/main/java/rxhttp/wrapper/converter/XmlConverter.java
class XmlConverter (line 23) | public class XmlConverter implements IConverter {
method XmlConverter (line 31) | private XmlConverter(Serializer serializer, boolean strict, MediaType ...
method create (line 37) | public static XmlConverter create() {
method create (line 41) | public static XmlConverter create(Serializer serializer) {
method create (line 45) | public static XmlConverter create(Serializer serializer, MediaType con...
method createNonStrict (line 49) | public static XmlConverter createNonStrict() {
method createNonStrict (line 53) | public static XmlConverter createNonStrict(Serializer serializer) {
method createNonStrict (line 58) | public static XmlConverter createNonStrict(Serializer serializer, Medi...
method convert (line 63) | @NotNull
method convert (line 98) | @SuppressWarnings("deprecation")
FILE: rxhttp/src/main/java/rxhttp/Platform.java
class Platform (line 16) | public class Platform {
method get (line 19) | public static Platform get() {
method Platform (line 23) | private Platform() {
method findPlatform (line 26) | private static Platform findPlatform() {
method isAndroid (line 38) | public boolean isAndroid() {
method sdkLessThan (line 42) | public boolean sdkLessThan(int api) {
method logi (line 46) | public void logi(String tag, String message) {
method logd (line 50) | public void logd(String tag, String message) {
method loge (line 54) | public void loge(String tag, String message) {
method loge (line 58) | public void loge(String tag, String message, Throwable e) {
method loge (line 63) | public void loge(String tag, Throwable e) {
class Android (line 67) | static final class Android extends Platform {
method Android (line 68) | Android() {
method isAndroid (line 72) | @Override
method sdkLessThan (line 77) | @Override
method logi (line 82) | @Override
method logd (line 87) | @Override
method loge (line 92) | @Override
method loge (line 97) | @Override
method loge (line 103) | @Override
method log (line 108) | private void log(int priority, String tag, String content) {
method printThrowable (line 124) | private void printThrowable(Throwable ex, String tag) {
FILE: rxhttp/src/main/java/rxhttp/RxHttpPlugins.java
class RxHttpPlugins (line 31) | public class RxHttpPlugins {
method RxHttpPlugins (line 46) | private RxHttpPlugins() {
method init (line 49) | public static RxHttpPlugins init(OkHttpClient okHttpClient) {
method isInit (line 54) | public static boolean isInit() {
method getOkHttpClient (line 58) | public static OkHttpClient getOkHttpClient() {
method newOkClientBuilder (line 64) | public static OkHttpClient.Builder newOkClientBuilder() {
method setDebug (line 68) | public RxHttpPlugins setDebug(boolean debug) {
method setDebug (line 72) | public RxHttpPlugins setDebug(boolean debug, boolean segmentPrint) {
method setDebug (line 76) | public RxHttpPlugins setDebug(boolean debug, boolean segmentPrint, int...
method setOnParamAssembly (line 85) | public RxHttpPlugins setOnParamAssembly(Consumer<? super Param<?>> onP...
method setResultDecoder (line 95) | public RxHttpPlugins setResultDecoder(Function<String, String> decoder) {
method setConverter (line 100) | public RxHttpPlugins setConverter(IConverter converter) {
method getConverter (line 107) | public static IConverter getConverter() {
method onParamAssembly (line 111) | public static void onParamAssembly(@NotNull Param<?> source) {
method onResultDecoder (line 120) | public static String onResultDecoder(String source) throws IOException {
method setCache (line 125) | public RxHttpPlugins setCache(File directory, long maxSize) {
method setCache (line 129) | public RxHttpPlugins setCache(File directory, long maxSize, long cache...
method setCache (line 133) | public RxHttpPlugins setCache(File directory, long maxSize, CacheMode ...
method setCache (line 137) | public RxHttpPlugins setCache(File directory, long maxSize, CacheMode ...
method getCacheStrategy (line 147) | public static CacheStrategy getCacheStrategy() {
method getCache (line 151) | public static InternalCache getCache() {
method getCacheOrThrow (line 158) | public static InternalCache getCacheOrThrow() {
method setExcludeCacheKeys (line 166) | public RxHttpPlugins setExcludeCacheKeys(String... keys) {
method getExcludeCacheKeys (line 171) | public static List<String> getExcludeCacheKeys() {
method cancelAll (line 176) | public static void cancelAll() {
method cancelAll (line 181) | public static void cancelAll(Object tag) {
method cancelAll (line 185) | public static void cancelAll(@Nullable OkHttpClient okClient) {
method cancelAll (line 190) | public static void cancelAll(@Nullable OkHttpClient okClient, @Nullabl...
method getDefaultOkHttpClient (line 208) | private static OkHttpClient getDefaultOkHttpClient() {
FILE: rxhttp/src/main/java/rxhttp/wrapper/OkHttpCompat.java
class OkHttpCompat (line 42) | public class OkHttpCompat {
method needDecodeResult (line 46) | public static boolean needDecodeResult(Response response) {
method closeQuietly (line 50) | public static void closeQuietly(Closeable... closeables) {
method buffer (line 58) | public static ResponseBody buffer(final ResponseBody body) throws IOEx...
method create (line 64) | public static RequestBody create(@Nullable MediaType contentType, Stri...
method create (line 68) | public static RequestBody create(final @Nullable MediaType contentType...
method create (line 72) | public static RequestBody create(final @Nullable MediaType contentType...
method part (line 77) | public static MultipartBody.Part part(RequestBody body) {
method part (line 81) | public static MultipartBody.Part part(@Nullable Headers headers, Reque...
method part (line 85) | public static MultipartBody.Part part(String name, @Nullable String fi...
method request (line 89) | public static Request request(Response response) {
method pathSegments (line 93) | public static List<String> pathSegments(Response response) {
method url (line 97) | public static HttpUrl url(Request request) {
method cookieJar (line 101) | public static CookieJar cookieJar(OkHttpClient okHttpClient) {
method header (line 105) | public static String header(Response response, String name) {
method isPartialContent (line 109) | public static boolean isPartialContent(Response response) {
method receivedResponseAtMillis (line 113) | public static long receivedResponseAtMillis(Response response) {
method throwIfFail (line 117) | @NotNull
method getContentLength (line 133) | public static long getContentLength(Response response) {
method parse (line 159) | public static StatusLine parse(String statusLine) throws IOException {
method newDiskLruCache (line 173) | public static DiskLruCache newDiskLruCache(File directory, int appVers...
method okHttpVersionCompare (line 212) | public static int okHttpVersionCompare(String version2) {
method getOkHttpUserAgent (line 219) | public static String getOkHttpUserAgent() {
method versionCompare (line 250) | private static int versionCompare(String version1, String version2) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/cache/CacheManager.java
class CacheManager (line 54) | public class CacheManager implements Closeable, Flushable {
method get (line 62) | @Nullable
method put (line 68) | @Override
method remove (line 73) | @Override
method removeAll (line 78) | @Override
method size (line 83) | @Override
method CacheManager (line 97) | public CacheManager(File directory, long maxSize) {
method md5 (line 102) | public static String md5(String key) {
method get (line 106) | @Nullable
method put (line 131) | private Response put(Response networkResponse, String key) throws IOEx...
method putResponse (line 136) | @Nullable
method cacheWritingResponse (line 154) | private okhttp3.Response cacheWritingResponse(final CacheRequest cache...
method remove (line 219) | private void remove(String key) throws IOException {
method abortQuietly (line 223) | private void abortQuietly(@Nullable DiskLruCache.Editor editor) {
method initialize (line 246) | public void initialize() throws IOException {
method delete (line 254) | private void delete() throws IOException {
method evictAll (line 262) | private void evictAll() throws IOException {
method urls (line 267) | public Iterator<String> urls() throws IOException {
method size (line 311) | public long size() throws IOException {
method maxSize (line 318) | public long maxSize() {
method flush (line 322) | @Override
method close (line 327) | @Override
method directory (line 332) | public File directory() {
method isClosed (line 336) | public boolean isClosed() {
class CacheRequestImpl (line 340) | private final class CacheRequestImpl implements CacheRequest {
method CacheRequestImpl (line 346) | CacheRequestImpl(final DiskLruCache.Editor editor) {
method abort (line 364) | @Override
method body (line 379) | @NotNull
class Entry (line 386) | private static final class Entry {
method Entry (line 456) | Entry(Source in) throws IOException {
method addUnsafeNonAscii (line 514) | void addUnsafeNonAscii(Headers.Builder builder, String line) {
method Entry (line 525) | Entry(Response response) {
method writeTo (line 538) | public void writeTo(DiskLruCache.Editor editor) throws IOException {
method isHttps (line 583) | private boolean isHttps() {
method readCertificateList (line 587) | private List<Certificate> readCertificateList(BufferedSource source)...
method writeCertList (line 607) | private void writeCertList(BufferedSink sink, List<Certificate> cert...
method matches (line 623) | public boolean matches(Request request, Response response) {
method response (line 629) | public Response response(Request request, DiskLruCache.Snapshot snap...
method readInt (line 647) | private static int readInt(BufferedSource source) throws IOException {
class CacheResponseBody (line 660) | private static class CacheResponseBody extends ResponseBody {
method CacheResponseBody (line 666) | CacheResponseBody(final DiskLruCache.Snapshot snapshot,
method contentType (line 682) | @Override
method contentLength (line 687) | @Override
method source (line 696) | @NotNull
FILE: rxhttp/src/main/java/rxhttp/wrapper/cache/CacheMode.java
type CacheMode (line 8) | public enum CacheMode {
FILE: rxhttp/src/main/java/rxhttp/wrapper/cache/CacheStrategy.java
class CacheStrategy (line 9) | public class CacheStrategy {
method CacheStrategy (line 15) | public CacheStrategy(CacheStrategy cacheStrategy) {
method CacheStrategy (line 21) | public CacheStrategy(CacheMode cacheMode) {
method CacheStrategy (line 25) | public CacheStrategy(CacheMode cacheMode, long cacheValidTime) {
method getCacheKey (line 30) | public String getCacheKey() {
method setCacheKey (line 34) | public void setCacheKey(String key) {
method getCacheValidTime (line 38) | public long getCacheValidTime() {
method setCacheValidTime (line 42) | public void setCacheValidTime(long validTime) {
method getCacheMode (line 49) | public CacheMode getCacheMode() {
method setCacheMode (line 53) | public void setCacheMode(CacheMode cacheMode) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/cache/HeadersVary.java
class HeadersVary (line 18) | class HeadersVary {
method varyMatches (line 24) | static boolean varyMatches(
method varyHeaders (line 36) | static Headers varyHeaders(Response response) {
method varyHeaders (line 49) | private static Headers varyHeaders(Headers requestHeaders, Headers res...
method varyFields (line 63) | private static Set<String> varyFields(Response response) {
method varyFields (line 70) | private static Set<String> varyFields(Headers responseHeaders) {
method equal (line 89) | private static boolean equal(Object a, Object b) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/cache/InternalCache.java
type InternalCache (line 13) | public interface InternalCache {
method get (line 14) | @Nullable
method put (line 17) | Response put(Response response, String key) throws IOException;
method remove (line 19) | void remove(String key) throws IOException;
method removeAll (line 21) | void removeAll() throws IOException;
method size (line 23) | long size() throws IOException;
FILE: rxhttp/src/main/java/rxhttp/wrapper/callback/Consumer.java
type Consumer (line 3) | public interface Consumer<T> {
method accept (line 5) | void accept(T t);
FILE: rxhttp/src/main/java/rxhttp/wrapper/callback/Function.java
type Function (line 5) | public interface Function<T, R> {
method apply (line 7) | R apply(T t) throws IOException;
FILE: rxhttp/src/main/java/rxhttp/wrapper/callback/IConverter.java
type IConverter (line 17) | public interface IConverter {
method convert (line 20) | @NotNull
method convert (line 24) | default <T> RequestBody convert(T value) throws IOException {
FILE: rxhttp/src/main/java/rxhttp/wrapper/callback/JsonConverter.java
type JsonConverter (line 11) | public interface JsonConverter extends IConverter {
FILE: rxhttp/src/main/java/rxhttp/wrapper/callback/ProgressCallback.java
type ProgressCallback (line 9) | public interface ProgressCallback {
method onProgress (line 11) | void onProgress(long currentSize, long totalSize, long speed);
FILE: rxhttp/src/main/java/rxhttp/wrapper/converter/GsonConverter.java
class GsonConverter (line 31) | public class GsonConverter implements JsonConverter {
method GsonConverter (line 36) | private GsonConverter(Gson gson, MediaType contentType) {
method create (line 41) | public static GsonConverter create() {
method create (line 45) | public static GsonConverter create(Gson gson) {
method create (line 49) | public static GsonConverter create(Gson gson, MediaType contentType) {
method convert (line 54) | @NotNull
method convert (line 81) | @SuppressWarnings("unchecked")
FILE: rxhttp/src/main/java/rxhttp/wrapper/cookie/CookieStore.java
class CookieStore (line 31) | public class CookieStore implements ICookieJar {
method CookieStore (line 40) | public CookieStore() {
method CookieStore (line 44) | public CookieStore(@Nullable File directory) {
method CookieStore (line 48) | public CookieStore(@Nullable File directory, boolean enabledMemory) {
method CookieStore (line 59) | public CookieStore(@Nullable File directory, long maxSize, boolean ena...
method getDiskLruCache (line 70) | private DiskLruCache getDiskLruCache() {
method saveCookie (line 83) | @Override
method saveCookie (line 96) | @Override
method loadCookie (line 136) | @Override
method matchCookies (line 168) | private List<Cookie> matchCookies(HttpUrl url, Map<String, Cookie> coo...
method getToken (line 180) | private String getToken(Cookie cookie) {
method removeCookie (line 189) | @Override
method removeAllCookie (line 208) | @Override
method readCookie (line 223) | private List<Cookie> readCookie(HttpUrl url, Source in) throws IOExcep...
method writeCookie (line 239) | private void writeCookie(DiskLruCache.Editor editor, Map<String, Cooki...
method abortQuietly (line 249) | private void abortQuietly(@Nullable DiskLruCache.Editor editor) {
method md5 (line 258) | private static String md5(String key) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/cookie/ICookieJar.java
type ICookieJar (line 16) | public interface ICookieJar extends CookieJar {
method saveFromResponse (line 18) | @Override
method loadForRequest (line 23) | @Override
method saveCookie (line 33) | void saveCookie(HttpUrl url, List<Cookie> cookies);
method saveCookie (line 40) | void saveCookie(HttpUrl url, Cookie cookie);
method loadCookie (line 47) | List<Cookie> loadCookie(HttpUrl url);
method removeCookie (line 53) | void removeCookie(HttpUrl url);
method removeAllCookie (line 58) | void removeAllCookie();
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/DownloadOffSize.java
class DownloadOffSize (line 8) | public class DownloadOffSize {
method DownloadOffSize (line 12) | public DownloadOffSize(long offSize) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/EmptyResponseBody.java
class EmptyResponseBody (line 14) | public final class EmptyResponseBody extends ResponseBody {
method EmptyResponseBody (line 18) | public EmptyResponseBody(@Nullable MediaType contentType, long content...
method contentType (line 23) | @Override
method contentLength (line 28) | @Override
method source (line 33) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/ExpandOutputStream.java
class ExpandOutputStream (line 19) | public final class ExpandOutputStream<T> extends OutputStream {
method ExpandOutputStream (line 24) | public ExpandOutputStream(T expand, OutputStream os) {
method open (line 29) | public static ExpandOutputStream<String> open(File file, boolean appen...
method open (line 33) | public static ExpandOutputStream<Uri> open(Context context, Uri uri, b...
method getExpand (line 38) | public T getExpand() {
method write (line 42) | @Override
method write (line 47) | @Override
method write (line 52) | @Override
method close (line 57) | @Override
method flush (line 62) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/FileRequestBody.java
class FileRequestBody (line 24) | public class FileRequestBody extends RequestBody {
method FileRequestBody (line 30) | public FileRequestBody(File file, long skipSize, @Nullable MediaType m...
method contentType (line 43) | @Override
method contentLength (line 48) | @Override
method writeTo (line 53) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/KeyValuePair.java
class KeyValuePair (line 11) | public class KeyValuePair {
method KeyValuePair (line 17) | public KeyValuePair(String key, @Nullable Object object) {
method KeyValuePair (line 21) | public KeyValuePair(String key, @Nullable Object value, boolean isEnco...
method getKey (line 27) | public String getKey() {
method getValue (line 31) | public Object getValue() {
method isEncoded (line 35) | public boolean isEncoded() {
method equals (line 39) | @Override
method hashCode (line 47) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/OkResponse.java
class OkResponse (line 15) | public final class OkResponse<T> {
method OkResponse (line 21) | private OkResponse(
method success (line 32) | public static <T> OkResponse<T> success(@Nullable T body, okhttp3.Resp...
method error (line 43) | public static <T> OkResponse<T> error(ResponseBody body, okhttp3.Respo...
method raw (line 55) | public okhttp3.Response raw() {
method code (line 62) | public int code() {
method message (line 69) | public String message() {
method headers (line 76) | public Headers headers() {
method isSuccessful (line 83) | public boolean isSuccessful() {
method body (line 90) | @Nullable
method errorBody (line 98) | @Nullable
method toString (line 103) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/ParameterizedTypeImpl.java
class ParameterizedTypeImpl (line 17) | public class ParameterizedTypeImpl implements ParameterizedType {
method ParameterizedTypeImpl (line 23) | public ParameterizedTypeImpl(Type rawType, Type actualType) {
method ParameterizedTypeImpl (line 27) | public ParameterizedTypeImpl(@Nullable Type ownerType, Type rawType, T...
method get (line 34) | public static ParameterizedType get(@NotNull Type rawType, @NotNull Ty...
method getParameterized (line 45) | public static ParameterizedType getParameterized(@NotNull Type rawType...
method getActualTypeArguments (line 54) | @Override
method getOwnerType (line 59) | @Override
method getRawType (line 64) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/Progress.java
class Progress (line 10) | public class Progress<T> {
method Progress (line 19) | public Progress(@Nullable T result) {
method Progress (line 24) | public Progress(long currentSize, long totalSize, long speed) {
method getResult (line 30) | @Nullable
method getSpeed (line 36) | public long getSpeed() {
method calculateRemainingTime (line 41) | public long calculateRemainingTime() {
method getProgress (line 52) | public int getProgress() {
method getFraction (line 57) | public float getFraction() {
method getCurrentSize (line 68) | public long getCurrentSize() {
method getTotalSize (line 72) | public long getTotalSize() {
method toString (line 76) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/UpFile.java
class UpFile (line 13) | public class UpFile {
method UpFile (line 20) | public UpFile(String key, String path) {
method UpFile (line 24) | public UpFile(String key, File file) {
method UpFile (line 28) | public UpFile(String key, File file, String filename) {
method UpFile (line 32) | public UpFile(@NotNull String key, @NotNull File file, @Nullable Strin...
method getKey (line 39) | public String getKey() {
method getFile (line 43) | public File getFile() {
method getFilename (line 47) | public String getFilename() {
method getSkipSize (line 51) | public long getSkipSize() {
FILE: rxhttp/src/main/java/rxhttp/wrapper/entity/UriRequestBody.java
class UriRequestBody (line 27) | public class UriRequestBody extends RequestBody {
method UriRequestBody (line 34) | public UriRequestBody(Context context, Uri uri, long skipSize, @Nullab...
method contentType (line 44) | @Override
method contentLength (line 49) | @Override
method writeTo (line 59) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/exception/CacheReadFailedException.java
class CacheReadFailedException (line 13) | public class CacheReadFailedException extends IOException {
method CacheReadFailedException (line 15) | public CacheReadFailedException(String message) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/exception/HttpStatusCodeException.java
class HttpStatusCodeException (line 20) | public final class HttpStatusCodeException extends IOException {
method HttpStatusCodeException (line 30) | public HttpStatusCodeException(Response response) {
method getLocalizedMessage (line 41) | @Override
method getStatusCode (line 46) | public int getStatusCode() {
method getRequestMethod (line 50) | public String getRequestMethod() {
method getRequestUrl (line 54) | public String getRequestUrl() {
method getHttpUrl (line 58) | public HttpUrl getHttpUrl() {
method getResponseHeaders (line 62) | public Headers getResponseHeaders() {
method getResponseBody (line 66) | public ResponseBody getResponseBody() {
method getResult (line 70) | public String getResult() throws IOException {
method toString (line 77) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/exception/ParseException.java
class ParseException (line 19) | public class ParseException extends IOException {
method ParseException (line 27) | public ParseException(@NotNull String code, String message, Response r...
method getErrorCode (line 37) | public String getErrorCode() {
method getRequestMethod (line 41) | public String getRequestMethod() {
method getRequestUrl (line 45) | public String getRequestUrl() {
method getHttpUrl (line 49) | public HttpUrl getHttpUrl() {
method getResponseHeaders (line 53) | public Headers getResponseHeaders() {
method getLocalizedMessage (line 57) | @Nullable
method toString (line 63) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/exception/ProxyException.java
class ProxyException (line 14) | public class ProxyException extends IOException {
method ProxyException (line 18) | public ProxyException(Request request, Throwable throwable) {
method ProxyException (line 22) | public ProxyException(String message, Throwable throwable) {
method toString (line 28) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/intercept/RangeInterceptor.java
class RangeInterceptor (line 18) | public class RangeInterceptor implements Interceptor {
method intercept (line 19) | @NotNull
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/AbstractBodyParam.java
class AbstractBodyParam (line 13) | public abstract class AbstractBodyParam<P extends AbstractBodyParam<P>> ...
method AbstractBodyParam (line 22) | public AbstractBodyParam(String url, Method method) {
method buildRequestBody (line 26) | @Override
method setProgressCallback (line 33) | public final P setProgressCallback(int minPeriod, ProgressCallback cal...
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/AbstractParam.java
class AbstractParam (line 32) | public abstract class AbstractParam<P extends Param<P>> extends Param<P> {
method AbstractParam (line 48) | public AbstractParam(@NotNull String url, Method method) {
method setUrl (line 54) | public P setUrl(@NotNull String url) {
method addPath (line 59) | @Override
method addEncodedPath (line 64) | @Override
method addPath (line 69) | private P addPath(KeyValuePair keyValuePair) {
method addQuery (line 75) | @Override
method addEncodedQuery (line 80) | @Override
method addQuery (line 85) | private P addQuery(KeyValuePair keyValuePair) {
method getQueryParam (line 91) | @Nullable
method getPaths (line 96) | public List<KeyValuePair> getPaths() {
method getUrl (line 100) | @Override
method getSimpleUrl (line 105) | @Override
method getHttpUrl (line 110) | @Override
method getMethod (line 115) | @Override
method getHeaders (line 120) | @Nullable
method getHeadersBuilder (line 126) | @Override
method setHeadersBuilder (line 133) | @Override
method cacheControl (line 139) | @Override
method tag (line 145) | @Override
method setAssemblyEnabled (line 151) | @Override
method isAssemblyEnabled (line 157) | @Override
method getRequestBuilder (line 162) | public Request.Builder getRequestBuilder() {
method getCacheStrategy (line 166) | @Override
method getCacheKey (line 174) | @Override
method setCacheKey (line 179) | @Override
method buildCacheKey (line 185) | public String buildCacheKey() {
method getCacheValidTime (line 190) | @Override
method setCacheValidTime (line 195) | @Override
method getCacheMode (line 201) | @Override
method setCacheMode (line 206) | @Override
method buildRequest (line 212) | @Override
method getConverter (line 218) | protected IConverter getConverter() {
method convert (line 224) | protected final RequestBody convert(Object object) {
method removeAllQuery (line 232) | @Override
method remove (line 238) | void remove(List<KeyValuePair> list, String key) {
method self (line 248) | @SuppressWarnings("unchecked")
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/FormParam.java
class FormParam (line 31) | public class FormParam extends AbstractBodyParam<FormParam> implements I...
method FormParam (line 42) | public FormParam(String url, Method method) {
method add (line 46) | @Override
method addEncoded (line 51) | public FormParam addEncoded(String key, @Nullable Object value) {
method addAllEncoded (line 55) | public FormParam addAllEncoded(Map<String, ?> map) {
method removeAllBody (line 62) | public FormParam removeAllBody(String key) {
method removeAllBody (line 67) | public FormParam removeAllBody() {
method set (line 74) | public FormParam set(String key, @Nullable Object value) {
method setEncoded (line 79) | public FormParam setEncoded(String key, @Nullable Object value) {
method add (line 84) | private FormParam add(KeyValuePair keyValuePair) {
method addPart (line 93) | @Override
method setMultiType (line 104) | public FormParam setMultiType(MediaType multiType) {
method isMultipart (line 109) | public boolean isMultipart() {
method getMultiType (line 113) | @Nullable
method getRequestBody (line 118) | @Override
method getPartList (line 124) | public List<Part> getPartList() {
method getBodyParam (line 128) | public List<KeyValuePair> getBodyParam() {
method buildCacheKey (line 132) | @Override
method toString (line 145) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/ICache.java
type ICache (line 11) | public interface ICache<P extends Param<P>> {
method setCacheKey (line 13) | P setCacheKey(String cacheKey);
method setCacheValidTime (line 15) | P setCacheValidTime(long cacheTime);
method setCacheMode (line 17) | P setCacheMode(CacheMode cacheMode);
method getCacheStrategy (line 19) | CacheStrategy getCacheStrategy();
method getCacheKey (line 21) | String getCacheKey();
method getCacheValidTime (line 23) | long getCacheValidTime();
method getCacheMode (line 25) | CacheMode getCacheMode();
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/IHeaders.java
type IHeaders (line 16) | @SuppressWarnings("unchecked")
method getHeaders (line 19) | Headers getHeaders();
method getHeadersBuilder (line 21) | Headers.Builder getHeadersBuilder();
method setHeadersBuilder (line 23) | P setHeadersBuilder(Headers.Builder builder);
method getHeader (line 25) | default String getHeader(String key) {
method addHeader (line 29) | default P addHeader(String key, String value) {
method addNonAsciiHeader (line 34) | default P addNonAsciiHeader(String key, String value) {
method setNonAsciiHeader (line 39) | default P setNonAsciiHeader(String key, String value) {
method addHeader (line 46) | default P addHeader(String line) {
method addAllHeader (line 51) | default P addAllHeader(@NotNull Map<String, String> headers) {
method addAllHeader (line 58) | default P addAllHeader(Headers headers) {
method setHeader (line 63) | default P setHeader(String key, String value) {
method setAllHeader (line 68) | default P setAllHeader(@NotNull Map<String, String> headers) {
method removeAllHeader (line 75) | default P removeAllHeader(String key) {
method setRangeHeader (line 86) | default P setRangeHeader(long startIndex) {
method setRangeHeader (line 100) | default P setRangeHeader(long startIndex, long endIndex) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/IParam.java
type IParam (line 17) | @SuppressWarnings("unchecked")
method setUrl (line 20) | P setUrl(@NotNull String url);
method add (line 22) | P add(String key, Object value);
method addPath (line 24) | P addPath(String name, Object value);
method addEncodedPath (line 26) | P addEncodedPath(String name, Object value);
method addAll (line 28) | default P addAll(@NotNull Map<String, ?> map) {
method addQuery (line 35) | P addQuery(String key, @Nullable Object value);
method addEncodedQuery (line 37) | P addEncodedQuery(String key, @Nullable Object value);
method removeAllQuery (line 39) | P removeAllQuery(String key);
method setQuery (line 41) | default P setQuery(String key, @Nullable Object value) {
method setEncodedQuery (line 46) | default P setEncodedQuery(String key, @Nullable Object value) {
method addAllQuery (line 51) | default P addAllQuery(String key, @Nullable List<?> values) {
method addAllEncodedQuery (line 59) | default P addAllEncodedQuery(String key, @Nullable List<?> values) {
method addAllQuery (line 67) | default P addAllQuery(@NotNull Map<String, ?> map) {
method addAllEncodedQuery (line 74) | default P addAllEncodedQuery(@NotNull Map<String, ?> map) {
method isAssemblyEnabled (line 84) | boolean isAssemblyEnabled();
method setAssemblyEnabled (line 92) | P setAssemblyEnabled(boolean enabled);
method tag (line 94) | default P tag(@Nullable Object tag) {
method tag (line 98) | <T> P tag(Class<? super T> type, @Nullable T tag);
method cacheControl (line 100) | P cacheControl(CacheControl cacheControl);
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/IPart.java
type IPart (line 10) | public interface IPart<P extends Param<P>> {
method addPart (line 12) | P addPart(Part part);
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/IRequest.java
type IRequest (line 15) | public interface IRequest {
method getUrl (line 20) | String getUrl();
method getSimpleUrl (line 25) | String getSimpleUrl();
method getHttpUrl (line 30) | HttpUrl getHttpUrl();
method getMethod (line 35) | Method getMethod();
method buildRequestBody (line 43) | default RequestBody buildRequestBody() {
method getRequestBody (line 47) | RequestBody getRequestBody();
method getHeaders (line 52) | Headers getHeaders();
method buildRequest (line 57) | Request buildRequest();
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/JsonArrayParam.java
class JsonArrayParam (line 35) | public class JsonArrayParam extends AbstractBodyParam<JsonArrayParam> {
method JsonArrayParam (line 43) | public JsonArrayParam(String url, Method method) {
method getRequestBody (line 47) | @Override
method add (line 61) | public JsonArrayParam add(@Nullable Object object) {
method add (line 67) | @Override
method addAll (line 74) | public JsonArrayParam addAll(String jsonElement) {
method addAll (line 84) | public JsonArrayParam addAll(JsonObject jsonObject) {
method addAll (line 88) | @Override
method addAll (line 94) | public JsonArrayParam addAll(JsonArray jsonArray) {
method addAll (line 98) | public JsonArrayParam addAll(List<?> list) {
method addJsonElement (line 106) | public JsonArrayParam addJsonElement(String jsonElement) {
method addJsonElement (line 111) | public JsonArrayParam addJsonElement(String key, String jsonElement) {
method getBodyParam (line 116) | @Nullable
method buildCacheKey (line 121) | @Override
method initList (line 131) | private void initList() {
method getConverter (line 135) | @Override
method toString (line 144) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/JsonParam.java
class JsonParam (line 35) | public class JsonParam extends AbstractBodyParam<JsonParam> {
method JsonParam (line 43) | public JsonParam(String url, Method method) {
method getRequestBody (line 47) | @Override
method add (line 55) | @Override
method addAll (line 62) | public JsonParam addAll(String jsonObject) {
method addAll (line 66) | public JsonParam addAll(JsonObject jsonObject) {
method addAll (line 70) | @Override
method addJsonElement (line 76) | public JsonParam addJsonElement(String key, String jsonElement) {
method getBodyParam (line 81) | public Map<String, Object> getBodyParam() {
method buildCacheKey (line 85) | @Override
method initMap (line 95) | private void initMap() {
method getConverter (line 99) | @Override
method toString (line 108) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/Method.java
type Method (line 9) | public enum Method {
method isGet (line 19) | public boolean isGet() {
method isPost (line 23) | public boolean isPost() {
method isHead (line 27) | public boolean isHead() {
method isPut (line 31) | public boolean isPut() {
method isPatch (line 35) | public boolean isPatch() {
method isDelete (line 39) | public boolean isDelete() {
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/NoBodyParam.java
class NoBodyParam (line 16) | public class NoBodyParam extends AbstractParam<NoBodyParam> {
method NoBodyParam (line 22) | public NoBodyParam(String url, Method method) {
method add (line 26) | @Override
method addEncoded (line 31) | public NoBodyParam addEncoded(String key, @Nullable Object value) {
method addAllEncoded (line 35) | public NoBodyParam addAllEncoded(@NotNull Map<String, ?> map) {
method getRequestBody (line 39) | @Override
method toString (line 44) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/param/Param.java
class Param (line 12) | public abstract class Param<P extends Param<P>> implements IParam<P>, IH...
method get (line 16) | public static NoBodyParam get(@NotNull String url) {
method head (line 20) | public static NoBodyParam head(@NotNull String url) {
method postBody (line 25) | public static BodyParam postBody(@NotNull String url) {
method putBody (line 29) | public static BodyParam putBody(@NotNull String url) {
method patchBody (line 33) | public static BodyParam patchBody(@NotNull String url) {
method deleteBody (line 37) | public static BodyParam deleteBody(@NotNull String url) {
method postForm (line 49) | public static FormParam postForm(@NotNull String url) {
method putForm (line 53) | public static FormParam putForm(@NotNull String url) {
method patchForm (line 57) | public static FormParam patchForm(@NotNull String url) {
method deleteForm (line 61) | public static FormParam deleteForm(@NotNull String url) {
method postJson (line 66) | public static JsonParam postJson(@NotNull String url) {
method putJson (line 70) | public static JsonParam putJson(@NotNull String url) {
method patchJson (line 74) | public static JsonParam patchJson(@NotNull String url) {
method deleteJson (line 78) | public static JsonParam deleteJson(@NotNull String url) {
method postJsonArray (line 83) | public static JsonArrayParam postJsonArray(@NotNull String url) {
method putJsonArray (line 87) | public static JsonArrayParam putJsonArray(@NotNull String url) {
method patchJsonArray (line 91) | public static JsonArrayParam patchJsonArray(@NotNull String url) {
method deleteJsonArray (line 95) | public static JsonArrayParam deleteJsonArray(@NotNull String url) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/parse/OkResponseParser.java
class OkResponseParser (line 18) | public class OkResponseParser<T> implements Parser<OkResponse<T>> {
method OkResponseParser (line 22) | public OkResponseParser(Parser<T> parser) {
method onParse (line 26) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/parse/Parser.java
type Parser (line 13) | public interface Parser<T> {
method onParse (line 15) | T onParse(Response response) throws IOException;
FILE: rxhttp/src/main/java/rxhttp/wrapper/parse/SmartParser.java
class SmartParser (line 16) | public class SmartParser<T> extends TypeParser<T> {
method SmartParser (line 18) | protected SmartParser() {
method SmartParser (line 21) | public SmartParser(Type type) {
method onParse (line 25) | @Override
method wrap (line 30) | @SuppressWarnings({"unchecked", "rawtypes"})
FILE: rxhttp/src/main/java/rxhttp/wrapper/parse/TypeParser.java
class TypeParser (line 13) | public abstract class TypeParser<T> implements Parser<T> {
method TypeParser (line 17) | public TypeParser() {
method TypeParser (line 21) | protected TypeParser(Type... types) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/progress/ProgressRequestBody.java
class ProgressRequestBody (line 17) | public class ProgressRequestBody extends RequestBody {
method ProgressRequestBody (line 24) | public ProgressRequestBody(@NotNull RequestBody requestBody, @NotNull ...
method getRequestBody (line 29) | @NotNull
method contentType (line 34) | @Override
method contentLength (line 39) | @Override
method writeTo (line 44) | @Override
method sink (line 57) | private Sink sink(Sink sink) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/ssl/HttpsUtils.java
class HttpsUtils (line 30) | public class HttpsUtils {
class SSLParams (line 31) | public static class SSLParams {
method getSslSocketFactory (line 36) | public static SSLParams getSslSocketFactory() {
method getSslSocketFactory (line 40) | public static SSLParams getSslSocketFactory(InputStream[] certificates...
class UnSafeTrustManager (line 61) | private static class UnSafeTrustManager implements X509TrustManager {
method checkClientTrusted (line 62) | @Override
method checkServerTrusted (line 67) | @Override
method getAcceptedIssuers (line 72) | @Override
method prepareTrustManager (line 78) | private static TrustManager[] prepareTrustManager(InputStream... certi...
method prepareKeyManager (line 111) | private static KeyManager[] prepareKeyManager(InputStream bksFile, Str...
method chooseTrustManager (line 129) | private static X509TrustManager chooseTrustManager(TrustManager[] trus...
class MyTrustManager (line 139) | private static class MyTrustManager implements X509TrustManager {
method MyTrustManager (line 143) | public MyTrustManager(X509TrustManager localTrustManager) throws NoS...
method checkClientTrusted (line 151) | @Override
method checkServerTrusted (line 156) | @Override
method getAcceptedIssuers (line 166) | @Override
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/BuildUtil.java
class BuildUtil (line 30) | public class BuildUtil {
method buildRequest (line 35) | public static Request buildRequest(@NotNull IRequest r, @NotNull Reque...
method buildFormBody (line 46) | public static RequestBody buildFormBody(List<KeyValuePair> pairs) {
method buildMultipartBody (line 64) | public static RequestBody buildMultipartBody(MediaType multiType, List...
method getHttpUrl (line 84) | public static HttpUrl getHttpUrl(@NotNull String url, @Nullable List<K...
method getMediaType (line 119) | public static MediaType getMediaType(@Nullable String filename) {
method getMediaTypeByUri (line 128) | public static MediaType getMediaTypeByUri(Context context, Uri uri) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/CacheUtil.java
class CacheUtil (line 19) | public class CacheUtil {
method excludeCacheKey (line 22) | @SuppressWarnings("unchecked")
method excludeCacheKey (line 45) | public static Map<?, ?> excludeCacheKey(Map<?, ?> param) {
method excludeCacheKey (line 59) | private static JsonObject excludeCacheKey(JsonObject jsonObject) {
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/Converter.java
class Converter (line 21) | public class Converter {
method convertTo (line 23) | public static <T> T convertTo(Response response, Type rawType, Type......
method convertToParameterized (line 27) | public static <T> T convertToParameterized(Response response, Type raw...
method convert (line 31) | @SuppressWarnings("unchecked")
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/GsonUtil.java
class GsonUtil (line 21) | public class GsonUtil {
method getObject (line 44) | @Nullable
method fromJson (line 54) | @NotNull
method toJson (line 64) | public static String toJson(Object object) {
method buildGson (line 69) | public static Gson buildGson() {
method newGson (line 73) | private static Gson newGson() {
method isEmpty (line 88) | private static boolean isEmpty(JsonElement jsonElement) {
class GsonHolder (line 97) | private static final class GsonHolder {
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/JSONStringer.java
class JSONStringer (line 15) | public class JSONStringer {
method JSONStringer (line 36) | public JSONStringer() {
method JSONStringer (line 40) | JSONStringer(int indentSpaces) {
method setSerializeCallback (line 46) | public JSONStringer setSerializeCallback(SerializeCallback serializeCa...
method write (line 51) | public JSONStringer write(Collection<?> list) throws JSONException {
method write (line 60) | public JSONStringer write(Map<?, ?> map) throws JSONException {
method write (line 69) | public JSONStringer write(JSONArray jsonArray) throws JSONException {
method write (line 79) | public JSONStringer write(JSONObject jsonObject) throws JSONException {
method array (line 96) | public JSONStringer array() throws JSONException {
method endArray (line 105) | public JSONStringer endArray() throws JSONException {
method object (line 115) | public JSONStringer object() throws JSONException {
method endObject (line 124) | public JSONStringer endObject() throws JSONException {
method open (line 133) | JSONStringer open(Scope empty, String openBracket) throws JSONException {
method close (line 148) | JSONStringer close(Scope empty, Scope nonempty, String closeBracket) t...
method peek (line 166) | private Scope peek() throws JSONException {
method replaceTop (line 177) | private void replaceTop(Scope topOfStack) {
method value (line 189) | public JSONStringer value(Object value) throws JSONException {
method value (line 237) | public JSONStringer value(boolean value) throws JSONException {
method value (line 253) | public JSONStringer value(double value) throws JSONException {
method value (line 267) | public JSONStringer value(long value) throws JSONException {
method string (line 276) | private void string(String value) {
method newline (line 327) | private void newline() {
method key (line 344) | public JSONStringer key(String name) throws JSONException {
method beforeKey (line 358) | private void beforeKey() throws JSONException {
method beforeValue (line 375) | private void beforeValue() throws JSONException {
method toString (line 405) | @Override
type Scope (line 415) | enum Scope {
type SerializeCallback (line 454) | public interface SerializeCallback {
method serialize (line 455) | String serialize(Object object);
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/LogTime.java
class LogTime (line 10) | public class LogTime {
method LogTime (line 14) | public LogTime() {
method tookMs (line 18) | public long tookMs() {
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/LogUtil.java
class LogUtil (line 44) | public class LogUtil {
method setDebug (line 59) | public static void setDebug(boolean debug, boolean segmentPrint, int i...
method isDebug (line 65) | public static boolean isDebug() {
method isSegmentPrint (line 69) | public static boolean isSegmentPrint() {
method logRxJavaError (line 74) | public static void logRxJavaError(Throwable throwable) {
method log (line 85) | public static void log(String message, Throwable throwable) {
method logCall (line 90) | public static void logCall(@Nullable Call call, Throwable e) {
method log (line 96) | public static void log(Throwable throwable) {
method log (line 102) | public static void log(String msg) {
method log (line 108) | public static void log(@NotNull Request userRequest, CookieJar cookieJ...
method log (line 173) | public static void log(@NotNull Response response, @NotNull LogTime lo...
method requestBody2Str (line 208) | private static String requestBody2Str(@NotNull RequestBody body) throw...
method multipartBody2Str (line 240) | private static String multipartBody2Str(MultipartBody multipartBody) {
method versionGte3140 (line 304) | private static boolean versionGte3140() {
method versionGte400 (line 308) | private static boolean versionGte400() {
method response2Str (line 312) | @SuppressWarnings("deprecation")
method formattingJson (line 333) | private static String formattingJson(String json, int indentSpaces) {
method isProbablyUtf8 (line 359) | private static boolean isProbablyUtf8(Buffer buffer) {
method getCharset (line 379) | private static Charset getCharset(RequestBody requestBody) {
method getCharset (line 384) | private static Charset getCharset(ResponseBody responseBody) {
method hostHeader (line 390) | private static String hostHeader(HttpUrl url) {
method cookieHeader (line 400) | private static String cookieHeader(List<Cookie> cookies) {
method bodyHasUnknownEncoding (line 412) | private static boolean bodyHasUnknownEncoding(Headers headers) {
method printBody (line 419) | private static boolean printBody(@NotNull ResponseBody responseBody) {
method readHeaders (line 444) | private static String readHeaders(Headers headers) {
method promisesBody (line 456) | @SuppressWarnings("deprecation")
FILE: rxhttp/src/main/java/rxhttp/wrapper/utils/TypeUtil.java
class TypeUtil (line 15) | public class TypeUtil {
method getActualTypeParameters (line 17) | public static Type[] getActualTypeParameters(Class<?> clazz) {
method getActualType (line 26) | @Nullable
FILE: rxhttp/src/test/java/rxhttp/wrapper/entity/ParameterizedTypeImplTest.java
class ParameterizedTypeImplTest (line 17) | public class ParameterizedTypeImplTest {
method testGet (line 19) | @Test
method getParameterized (line 69) | @Test
Condensed preview — 230 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (828K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 846,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".gitignore",
"chars": 1140,
"preview": "# Built application files\n*.apk\n*.ap_\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated file"
},
{
"path": "LICENSE",
"chars": 11019,
"preview": " Apache License\n Version 2.0, January 2004\n h"
},
{
"path": "README.md",
"chars": 9702,
"preview": "# RxHttp\n\nEnglish | [中文文档](https://github.com/liujingxing/rxhttp/blob/master/README_zh.md)\n\n[ | 中文文档\n\n[\n alias(libs.plugins.kotlin.android)\n id 'kotlin-kapt'\n id"
},
{
"path": "app/proguard-rules.pro",
"chars": 2482,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "app/src/androidTest/java/com/example/httpsender/ExampleInstrumentedTest.java",
"chars": 1261,
"preview": "package com.example.httpsender;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport androidx.test.ext.juni"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 1129,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n <uses-"
},
{
"path": "app/src/main/java/com/example/httpsender/AppHolder.java",
"chars": 637,
"preview": "package com.example.httpsender;\n\nimport android.app.Application;\nimport android.content.Context;\n\nimport androidx.multid"
},
{
"path": "app/src/main/java/com/example/httpsender/DownloadMultiAdapter.java",
"chars": 4963,
"preview": "package com.example.httpsender;\n\nimport android.annotation.SuppressLint;\nimport android.view.LayoutInflater;\nimport andr"
},
{
"path": "app/src/main/java/com/example/httpsender/ExceptionHelper.java",
"chars": 733,
"preview": "package com.example.httpsender;\n\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport android"
},
{
"path": "app/src/main/java/com/example/httpsender/LoggingEventListener.kt",
"chars": 4328,
"preview": "package com.example.httpsender\n\nimport android.util.Log\nimport okhttp3.Call\nimport okhttp3.Connection\nimport okhttp3.Eve"
},
{
"path": "app/src/main/java/com/example/httpsender/MainActivity.java",
"chars": 5745,
"preview": "package com.example.httpsender;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.os.Bundle"
},
{
"path": "app/src/main/java/com/example/httpsender/MyViewModel.kt",
"chars": 1357,
"preview": "package com.example.httpsender\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.lifecycle.viewMod"
},
{
"path": "app/src/main/java/com/example/httpsender/OnError.java",
"chars": 452,
"preview": "package com.example.httpsender;\n\n\nimport com.example.httpsender.entity.ErrorInfo;\n\nimport io.reactivex.rxjava3.functions"
},
{
"path": "app/src/main/java/com/example/httpsender/Presenter.kt",
"chars": 1608,
"preview": "package com.example.httpsender\n\nimport android.util.Log\nimport androidx.lifecycle.LifecycleOwner\nimport com.example.http"
},
{
"path": "app/src/main/java/com/example/httpsender/RxHttpManager.java",
"chars": 3126,
"preview": "package com.example.httpsender;\n\n\nimport android.app.Application;\n\nimport java.io.File;\nimport java.util.concurrent.Time"
},
{
"path": "app/src/main/java/com/example/httpsender/Tip.java",
"chars": 1225,
"preview": "package com.example.httpsender;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.widget.Toast;\n\n\n/**"
},
{
"path": "app/src/main/java/com/example/httpsender/ToolBarActivity.java",
"chars": 2422,
"preview": "package com.example.httpsender;\n\nimport android.os.Build;\nimport android.view.MenuItem;\nimport android.view.ViewGroup;\n\n"
},
{
"path": "app/src/main/java/com/example/httpsender/adapter/FragmentPageAdapter.java",
"chars": 1127,
"preview": "package com.example.httpsender.adapter;\n\n\n\nimport androidx.fragment.app.Fragment;\nimport androidx.fragment.app.FragmentM"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/Article.java",
"chars": 5975,
"preview": "package com.example.httpsender.entity;\n\n/**\n * 文章实体类\n * User: ljx\n * Date: 2019-09-24\n * Time: 10:23\n */\npublic class Ar"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/DownloadTask.java",
"chars": 1996,
"preview": "package com.example.httpsender.entity;\n\n\n\n/**\n * User: ljx\n * Date: 2019-06-08\n * Time: 10:09\n */\npublic class DownloadT"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/ErrorInfo.java",
"chars": 3325,
"preview": "package com.example.httpsender.entity;\n\nimport android.text.TextUtils;\n\nimport com.example.httpsender.AppHolder;\nimport "
},
{
"path": "app/src/main/java/com/example/httpsender/entity/Location.java",
"chars": 450,
"preview": "package com.example.httpsender.entity;\n\n/**\n * User: ljx\n * Date: 2019-11-18\n * Time: 14:51\n */\npublic class Location {\n"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/Name.java",
"chars": 330,
"preview": "package com.example.httpsender.entity;\n\n/**\n * User: ljx\n * Date: 2019-11-18\n * Time: 16:19\n */\npublic class Name {\n\n "
},
{
"path": "app/src/main/java/com/example/httpsender/entity/NewsDataXml.java",
"chars": 537,
"preview": "package com.example.httpsender.entity;\n\nimport org.simpleframework.xml.Attribute;\nimport org.simpleframework.xml.Element"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/NewsXml.java",
"chars": 332,
"preview": "package com.example.httpsender.entity;\n\nimport org.simpleframework.xml.Attribute;\nimport org.simpleframework.xml.Root;\n\n"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/PageList.java",
"chars": 881,
"preview": "package com.example.httpsender.entity;\n\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * User: ljx\n * Date: 2"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/Response.java",
"chars": 629,
"preview": "package com.example.httpsender.entity;\n\n\n/**\n * User: ljx\n * Date: 2018/10/21\n * Time: 13:16\n */\npublic class Response<T"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/Url.kt",
"chars": 458,
"preview": "package com.example.httpsender.entity\n\nimport rxhttp.wrapper.annotation.DefaultDomain\nimport rxhttp.wrapper.annotation.D"
},
{
"path": "app/src/main/java/com/example/httpsender/entity/User.java",
"chars": 541,
"preview": "package com.example.httpsender.entity;\n\n/**\n * User: ljx\n * Date: 2019-12-04\n * Time: 12:13\n */\npublic class User {\n\n "
},
{
"path": "app/src/main/java/com/example/httpsender/fragment/AwaitFragment.kt",
"chars": 11058,
"preview": "package com.example.httpsender.fragment\n\nimport android.graphics.Color\nimport android.net.Uri\nimport android.os.Bundle\ni"
},
{
"path": "app/src/main/java/com/example/httpsender/fragment/BaseFragment.kt",
"chars": 1101,
"preview": "package com.example.httpsender.fragment\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view"
},
{
"path": "app/src/main/java/com/example/httpsender/fragment/FlowFragment.kt",
"chars": 10708,
"preview": "package com.example.httpsender.fragment\n\nimport android.graphics.Color\nimport android.net.Uri\nimport android.os.Bundle\ni"
},
{
"path": "app/src/main/java/com/example/httpsender/fragment/MultiDownloadFragment.java",
"chars": 7683,
"preview": "package com.example.httpsender.fragment;\n\nimport android.os.Bundle;\nimport android.view.View;\nimport android.view.View.O"
},
{
"path": "app/src/main/java/com/example/httpsender/fragment/RxJavaFragment.kt",
"chars": 11842,
"preview": "package com.example.httpsender.fragment\n\nimport android.graphics.Color\nimport android.net.Uri\nimport android.os.Bundle\ni"
},
{
"path": "app/src/main/java/com/example/httpsender/interceptor/RedirectInterceptor.java",
"chars": 838,
"preview": "package com.example.httpsender.interceptor;\n\nimport java.io.IOException;\n\nimport okhttp3.Interceptor;\nimport okhttp3.Req"
},
{
"path": "app/src/main/java/com/example/httpsender/interceptor/TokenInterceptor.java",
"chars": 2193,
"preview": "package com.example.httpsender.interceptor;\n\n\nimport com.example.httpsender.entity.User;\n\nimport org.jetbrains.annotatio"
},
{
"path": "app/src/main/java/com/example/httpsender/kt/Activity.kt",
"chars": 641,
"preview": "package com.example.httpsender.kt\n\nimport android.app.Activity\nimport android.content.Intent\nimport androidx.fragment.ap"
},
{
"path": "app/src/main/java/com/example/httpsender/kt/KotlinExtensions.kt",
"chars": 2249,
"preview": "package com.example.httpsender.kt\n\nimport android.content.Context\nimport android.net.ConnectivityManager\nimport com.exam"
},
{
"path": "app/src/main/java/com/example/httpsender/kt/Uri.kt",
"chars": 1528,
"preview": "package com.example.httpsender.kt\n\nimport android.content.Context\nimport android.net.Uri\nimport android.provider.MediaSt"
},
{
"path": "app/src/main/java/com/example/httpsender/param/GetEncryptParam.java",
"chars": 1444,
"preview": "package com.example.httpsender.param;\n\nimport android.graphics.Point;\n\nimport java.io.IOException;\nimport java.util.List"
},
{
"path": "app/src/main/java/com/example/httpsender/param/PostEncryptFormParam.java",
"chars": 875,
"preview": "package com.example.httpsender.param;\n\nimport rxhttp.wrapper.annotation.Param;\nimport rxhttp.wrapper.param.FormParam;\nim"
},
{
"path": "app/src/main/java/com/example/httpsender/param/PostEncryptJsonParam.kt",
"chars": 1228,
"preview": "package com.example.httpsender.param\n\n\nimport okhttp3.MediaType\nimport okhttp3.MediaType.Companion.toMediaType\nimport ok"
},
{
"path": "app/src/main/java/com/example/httpsender/param/PostEncryptJsonParam1.java",
"chars": 686,
"preview": "package com.example.httpsender.param;\n\nimport okhttp3.RequestBody;\nimport rxhttp.wrapper.annotation.Param;\nimport rxhttp"
},
{
"path": "app/src/main/java/com/example/httpsender/parser/Android10DownloadFactory.kt",
"chars": 2721,
"preview": "package com.example.httpsender.parser\n\nimport android.content.ContentValues\nimport android.content.Context\nimport androi"
},
{
"path": "app/src/main/java/com/example/httpsender/parser/ResponseParser.kt",
"chars": 2111,
"preview": "package com.example.httpsender.parser\n\nimport com.example.httpsender.entity.PageList\nimport com.example.httpsender.entit"
},
{
"path": "app/src/main/java/com/example/httpsender/parser/java/DoubleTypeParser.java",
"chars": 1261,
"preview": "package com.example.httpsender.parser.java;\n\nimport android.util.Pair;\n\nimport com.example.httpsender.entity.Response;\n\n"
},
{
"path": "app/src/main/java/com/example/httpsender/parser/java/ResponseParser.java",
"chars": 2137,
"preview": "package com.example.httpsender.parser.java;\n\nimport com.example.httpsender.entity.Response;\n\nimport org.jetbrains.annota"
},
{
"path": "app/src/main/java/com/example/httpsender/utils/Preferences.java",
"chars": 2197,
"preview": "package com.example.httpsender.utils;\n\nimport android.content.SharedPreferences;\nimport android.preference.PreferenceMan"
},
{
"path": "app/src/main/java/com/example/httpsender/view/ScaleTransitionPagerTitleView.java",
"chars": 1284,
"preview": "package com.example.httpsender.view;\n\nimport android.content.Context;\n\nimport net.lucode.hackware.magicindicator.buildin"
},
{
"path": "app/src/main/java/com/example/httpsender/vm/MultiTaskAwaitDownloader.kt",
"chars": 5778,
"preview": "package com.example.httpsender.vm\n\nimport androidx.lifecycle.MutableLiveData\nimport com.example.httpsender.Tip\nimport co"
},
{
"path": "app/src/main/java/com/example/httpsender/vm/MultiTaskDownloader.kt",
"chars": 5743,
"preview": "package com.example.httpsender.vm\n\nimport android.annotation.SuppressLint\nimport androidx.lifecycle.MutableLiveData\nimpo"
},
{
"path": "app/src/main/java/com/example/httpsender/vm/MultiTaskFlowDownloader.kt",
"chars": 5791,
"preview": "package com.example.httpsender.vm\n\nimport androidx.lifecycle.MutableLiveData\nimport com.example.httpsender.Tip\nimport co"
},
{
"path": "app/src/main/res/drawable/ic_launcher_background.xml",
"chars": 5606,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:wi"
},
{
"path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
"chars": 1880,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:aapt=\"http://schemas.android.com/aapt\"\n "
},
{
"path": "app/src/main/res/layout/await_fragment.xml",
"chars": 6452,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tool"
},
{
"path": "app/src/main/res/layout/download_multi_adapter.xml",
"chars": 2490,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
},
{
"path": "app/src/main/res/layout/flow_fragment.xml",
"chars": 6452,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tool"
},
{
"path": "app/src/main/res/layout/main_activity.xml",
"chars": 1078,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app="
},
{
"path": "app/src/main/res/layout/multi_download_fragment.xml",
"chars": 1986,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app="
},
{
"path": "app/src/main/res/layout/rxjava_fragment.xml",
"chars": 6452,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tool"
},
{
"path": "app/src/main/res/layout/toolbar_activity.xml",
"chars": 692,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/menu/download.xml",
"chars": 284,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"h"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
"chars": 272,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 208,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">#008577</color>\n <color name=\"color"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 324,
"preview": "<resources>\n <string name=\"app_name\">RxHttp</string>\n\n <string name=\"network_error\">当前无网络,请检查你的网络设置</string>\n <"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 376,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">"
},
{
"path": "app/src/main/res/values/themes.xml",
"chars": 404,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n <style name=\"ToolbarTheme\" parent=\"ThemeOverlay.AppCompat.Action"
},
{
"path": "app/src/main/res/xml/network_config.xml",
"chars": 144,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n <base-config cleartextTrafficPermitted=\"true\" />\n</"
},
{
"path": "app/src/test/java/com/rxhttp/compiler/AbstractTestSymbolProcessor.kt",
"chars": 841,
"preview": "package com.rxhttp.compiler\n\nimport com.google.devtools.ksp.processing.*\nimport com.google.devtools.ksp.symbol.KSAnnotat"
},
{
"path": "app/src/test/java/com/rxhttp/compiler/KspProcessorTest.kt",
"chars": 3405,
"preview": "package com.rxhttp.compiler\n\nimport com.google.devtools.ksp.processing.CodeGenerator\nimport com.google.devtools.ksp.proc"
},
{
"path": "app/src/test/java/com/rxhttp/compiler/TestParser1.kt",
"chars": 314,
"preview": "package com.rxhttp.compiler\n\nimport rxhttp.wrapper.parse.TypeParser\n\n/**\n * User: ljx\n * Date: 2023/8/28\n * Time: 11:12\n"
},
{
"path": "app/src/test/java/com/rxhttp/compiler/TestParser2.kt",
"chars": 773,
"preview": "package com.rxhttp.compiler\n\nimport com.example.httpsender.entity.Response\nimport com.example.httpsender.entity.User\nimp"
},
{
"path": "app/src/test/java/com.example.httpsender/AsyncTest.java",
"chars": 3809,
"preview": "package com.example.httpsender;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse"
},
{
"path": "build.gradle",
"chars": 118,
"preview": "plugins {\n alias(libs.plugins.android.application) apply false\n alias(libs.plugins.kotlin.android) apply false\n}"
},
{
"path": "gradle/libs.versions.toml",
"chars": 5381,
"preview": "[versions]\nagp = \"9.0.0\"\nkotlin = \"2.3.10\"\nandroid = \"4.1.1.4\"\nappcompat = \"1.7.1\"\nconstraintlayout = \"2.2.1\"\nfastjson ="
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 232,
"preview": "#Tue Oct 13 10:34:15 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 1298,
"preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
},
{
"path": "jitpack.yml",
"chars": 19,
"preview": "jdk:\n - openjdk17\n"
},
{
"path": "maven.gradle",
"chars": 149,
"preview": "apply plugin: 'maven-publish'\n\npublishing {\n publications {\n release(MavenPublication) {\n from comp"
},
{
"path": "maven_dependency.md",
"chars": 2071,
"preview": "## 注意\n\n- RxHttp支持`RxJava2和RxJava3`,依赖时需要选择对应的注解处理器,如不需要支持RxJava,则可不选择注解处理器\n\n```xml\n<dependencies>\n\n <!--必须-->\n <de"
},
{
"path": "rxhttp/build.gradle",
"chars": 1015,
"preview": "import org.jetbrains.kotlin.gradle.dsl.JvmTarget\n\nplugins {\n id 'java-library'\n id 'org.jetbrains.kotlin.jvm'\n}\nap"
},
{
"path": "rxhttp/src/main/java/rxhttp/AwaitTransform.kt",
"chars": 8479,
"preview": "package rxhttp\n\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.CoroutineStart\nimport kotlinx.corouti"
},
{
"path": "rxhttp/src/main/java/rxhttp/CallFactoryExt.kt",
"chars": 2587,
"preview": "package rxhttp\n\nimport android.content.Context\nimport android.net.Uri\nimport rxhttp.wrapper.CallFactory\nimport rxhttp.wr"
},
{
"path": "rxhttp/src/main/java/rxhttp/Platform.java",
"chars": 3797,
"preview": "package rxhttp;\n\nimport android.os.Build;\nimport android.util.Log;\n\nimport java.io.PrintWriter;\nimport java.io.StringWri"
},
{
"path": "rxhttp/src/main/java/rxhttp/RxHttpPlugins.java",
"chars": 6600,
"preview": "package rxhttp;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.io.Fi"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/CallFactory.kt",
"chars": 359,
"preview": "package rxhttp.wrapper\n\nimport okhttp3.Call\nimport rxhttp.wrapper.param.AbstractBodyParam\n\n/**\n * User: ljx\n * Date: 202"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/OkHttpCompat.java",
"chars": 10337,
"preview": "package rxhttp.wrapper;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport ja"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cache/CacheManager.java",
"chars": 25713,
"preview": "package rxhttp.wrapper.cache;\n\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\n\nimport org.jetbrains.annotatio"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cache/CacheMode.java",
"chars": 527,
"preview": "package rxhttp.wrapper.cache;\n\n/**\n * User: ljx\n * Date: 2019-12-15\n * Time: 13:57\n */\npublic enum CacheMode {\n\n /**\n"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cache/CacheStrategy.java",
"chars": 1380,
"preview": "package rxhttp.wrapper.cache;\n\n/**\n * 缓存策略\n * User: ljx\n * Date: 2019-12-15\n * Time: 20:58\n */\npublic class CacheStrateg"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cache/HeadersVary.java",
"chars": 3044,
"preview": "package rxhttp.wrapper.cache;\n\nimport java.util.Collections;\nimport java.util.Objects;\nimport java.util.Set;\nimport java"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cache/InternalCache.java",
"chars": 585,
"preview": "package rxhttp.wrapper.cache;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.io.IOException;\n\nimport okhttp3.R"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/Consumer.java",
"chars": 90,
"preview": "package rxhttp.wrapper.callback;\n\npublic interface Consumer<T> {\n\n void accept(T t);\n}\n"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/Function.java",
"chars": 137,
"preview": "package rxhttp.wrapper.callback;\n\nimport java.io.IOException;\n\npublic interface Function<T, R> {\n\n R apply(T t) throw"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/IConverter.java",
"chars": 602,
"preview": "package rxhttp.wrapper.callback;\n\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\nimport java.la"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/JsonConverter.java",
"chars": 251,
"preview": "package rxhttp.wrapper.callback;\n\n\nimport okhttp3.MediaType;\n\n/**\n * User: ljx\n * Date: 2021-10-15\n * Time: 22:54\n */\npu"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/OutputStreamFactory.kt",
"chars": 4054,
"preview": "package rxhttp.wrapper.callback\n\nimport android.content.Context\nimport android.net.Uri\nimport okhttp3.Response\nimport rx"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/ProgressCallback.java",
"chars": 196,
"preview": "package rxhttp.wrapper.callback;\n\n\n/**\n * User: ljx\n * Date: 2017/12/1\n * Time: 20:22\n */\npublic interface ProgressCallb"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/callback/ProgressCallbackHelper.kt",
"chars": 1399,
"preview": "package rxhttp.wrapper.callback\n\nimport android.os.SystemClock\nimport rxhttp.wrapper.utils.Speeder\n\n\n/**\n * User: ljx\n *"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/converter/GsonConverter.java",
"chars": 2876,
"preview": "package rxhttp.wrapper.converter;\n\n\nimport com.google.gson.Gson;\nimport com.google.gson.TypeAdapter;\nimport com.google.g"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cookie/CookieStore.java",
"chars": 7948,
"preview": "package rxhttp.wrapper.cookie;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.io.File;\nimport java.io.IOExcept"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/cookie/ICookieJar.java",
"chars": 1125,
"preview": "package rxhttp.wrapper.cookie;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\n\nimport okhttp3.Cookie"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/coroutines/Await.kt",
"chars": 142,
"preview": "package rxhttp.wrapper.coroutines\n\n/**\n * User: ljx\n * Date: 2020/3/21\n * Time: 17:06\n */\ninterface Await<T> {\n\n susp"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/coroutines/CallAwait.kt",
"chars": 832,
"preview": "package rxhttp.wrapper.coroutines\n\nimport okhttp3.Call\nimport rxhttp.wrapper.CallFactory\nimport rxhttp.wrapper.entity.Ok"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/coroutines/CallFlow.kt",
"chars": 3005,
"preview": "package rxhttp.wrapper.coroutines\n\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.channel"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/DownloadOffSize.java",
"chars": 234,
"preview": "package rxhttp.wrapper.entity;\n\n/**\n * User: ljx\n * Date: 2022/9/27\n * Time: 17:13\n */\npublic class DownloadOffSize {\n\n "
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/EmptyResponseBody.java",
"chars": 864,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport okhttp3.MediaType;\nimport okhttp3.Res"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/ExpandOutputStream.java",
"chars": 1634,
"preview": "package rxhttp.wrapper.entity;\n\nimport android.content.Context;\nimport android.net.Uri;\n\nimport org.jetbrains.annotation"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/FileRequestBody.java",
"chars": 2112,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/KeyValuePair.java",
"chars": 1073,
"preview": "package rxhttp.wrapper.entity;\n\n\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * User: ljx\n * Date: 2019-11-15\n * Tim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/OkResponse.java",
"chars": 2760,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.Objects;\n\nimport okhttp3.He"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/ParameterizedTypeImpl.java",
"chars": 2107,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/Progress.java",
"chars": 2150,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * User: ljx\n * Date: 2019/1/20\n * Time:"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/UpFile.java",
"chars": 1100,
"preview": "package rxhttp.wrapper.entity;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/entity/UriRequestBody.java",
"chars": 2401,
"preview": "package rxhttp.wrapper.entity;\n\nimport android.content.ContentResolver;\nimport android.content.Context;\nimport android.n"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/exception/CacheReadFailedException.java",
"chars": 357,
"preview": "package rxhttp.wrapper.exception;\n\nimport java.io.IOException;\n\nimport rxhttp.wrapper.cache.CacheMode;\n\n/**\n * 缓存读取失败异常,"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/exception/HttpStatusCodeException.java",
"chars": 1981,
"preview": "package rxhttp.wrapper.exception;\n\nimport java.io.IOException;\n\nimport okhttp3.Headers;\nimport okhttp3.HttpUrl;\nimport o"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/exception/ParseException.java",
"chars": 1625,
"preview": "package rxhttp.wrapper.exception;\n\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/exception/ProxyException.java",
"chars": 737,
"preview": "package rxhttp.wrapper.exception;\n\n\nimport java.io.IOException;\n\nimport okhttp3.Request;\n\n/**\n * The purpose of this cla"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/intercept/CacheInterceptor.kt",
"chars": 2760,
"preview": "package rxhttp.wrapper.intercept\n\nimport okhttp3.Interceptor\nimport okhttp3.Request\nimport okhttp3.Response\nimport rxhtt"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/intercept/LogInterceptor.kt",
"chars": 782,
"preview": "package rxhttp.wrapper.intercept\n\nimport okhttp3.Interceptor\nimport okhttp3.OkHttpClient\nimport okhttp3.Response\nimport "
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/intercept/RangeInterceptor.java",
"chars": 1038,
"preview": "package rxhttp.wrapper.intercept;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\n\nimport okhttp"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/AbstractBodyParam.java",
"chars": 1148,
"preview": "package rxhttp.wrapper.param;\n\nimport okhttp3.RequestBody;\nimport rxhttp.wrapper.callback.ProgressCallback;\nimport rxhtt"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/AbstractParam.java",
"chars": 6547,
"preview": "package rxhttp.wrapper.param;\n\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/BodyParam.kt",
"chars": 1058,
"preview": "package rxhttp.wrapper.param\n\nimport okhttp3.RequestBody\n\n/**\n * User: ljx\n * Date: 2019-09-11\n * Time: 11:52\n *\n * @par"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/FormParam.java",
"chars": 4289,
"preview": "package rxhttp.wrapper.param;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util."
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/ICache.java",
"chars": 468,
"preview": "package rxhttp.wrapper.param;\n\nimport rxhttp.wrapper.cache.CacheMode;\nimport rxhttp.wrapper.cache.CacheStrategy;\n\n/**\n *"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/IHeaders.java",
"chars": 2688,
"preview": "package rxhttp.wrapper.param;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.Map;\nimport java.util.Map.Ent"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/IParam.java",
"chars": 2507,
"preview": "package rxhttp.wrapper.param;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimp"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/IPart.java",
"chars": 197,
"preview": "package rxhttp.wrapper.param;\n\nimport okhttp3.MultipartBody.Part;\n\n/**\n * User: ljx\n * Date: 2019-05-19\n * Time: 18:18\n "
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/IRequest.java",
"chars": 895,
"preview": "package rxhttp.wrapper.param;\n\n\nimport okhttp3.Headers;\nimport okhttp3.HttpUrl;\nimport okhttp3.Request;\nimport okhttp3.R"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/JsonArrayParam.java",
"chars": 4419,
"preview": "package rxhttp.wrapper.param;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.g"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/JsonParam.java",
"chars": 3354,
"preview": "package rxhttp.wrapper.param;\n\n\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/Method.java",
"chars": 638,
"preview": "package rxhttp.wrapper.param;\n\n/**\n * 请求方法\n * User: ljx\n * Date: 2019-09-10\n * Time: 23:18\n */\npublic enum Method {\n\n "
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/NoBodyParam.java",
"chars": 1139,
"preview": "package rxhttp.wrapper.param;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimp"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/param/Param.java",
"chars": 2875,
"preview": "package rxhttp.wrapper.param;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport okhttp3.MediaType;\n\n/**\n * User: ljx\n *"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/parse/OkResponseParser.java",
"chars": 1617,
"preview": "package rxhttp.wrapper.parse;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\n\nimport okhttp3.Re"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/parse/Parser.java",
"chars": 253,
"preview": "package rxhttp.wrapper.parse;\n\nimport java.io.IOException;\n\nimport okhttp3.Response;\n\n/**\n *[okhttp3.Response] to T\n * U"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/parse/SmartParser.java",
"chars": 931,
"preview": "package rxhttp.wrapper.parse;\n\nimport java.io.IOException;\nimport java.lang.reflect.Type;\n\nimport okhttp3.Response;\nimpo"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/parse/StreamParser.kt",
"chars": 2434,
"preview": "package rxhttp.wrapper.parse\n\nimport okhttp3.Response\nimport rxhttp.wrapper.OkHttpCompat\nimport rxhttp.wrapper.callback."
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/parse/TypeParser.java",
"chars": 427,
"preview": "package rxhttp.wrapper.parse;\n\nimport java.lang.reflect.Type;\n\nimport rxhttp.wrapper.utils.TypeUtil;\n\n\n/**\n * User: ljx\n"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/progress/ProgressRequestBody.java",
"chars": 2039,
"preview": "package rxhttp.wrapper.progress;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\n\nimport okhttp3"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/ssl/HttpsUtils.java",
"chars": 6444,
"preview": "package rxhttp.wrapper.ssl;\n\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.security.KeyManagement"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/BuildUtil.java",
"chars": 5080,
"preview": "package rxhttp.wrapper.utils;\n\nimport android.content.ContentResolver;\nimport android.content.Context;\nimport android.ne"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/CacheUtil.java",
"chars": 2581,
"preview": "package rxhttp.wrapper.utils;\n\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\n\nimport java.util."
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Converter.java",
"chars": 1646,
"preview": "package rxhttp.wrapper.utils;\n\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\n\nimport java.io.IO"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Converter.kt",
"chars": 931,
"preview": "package rxhttp.wrapper.utils\n\nimport okhttp3.Response\nimport java.io.IOException\nimport java.lang.reflect.Type\nimport ko"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/GsonUtil.java",
"chars": 3079,
"preview": "package rxhttp.wrapper.utils;\n\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson."
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/JSONStringer.java",
"chars": 12797,
"preview": "package rxhttp.wrapper.utils;\n\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nim"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Json.kt",
"chars": 1623,
"preview": "@file:JvmName(\"JsonUtil\")\n\npackage rxhttp.wrapper.utils\n\nimport com.google.gson.JsonArray\nimport com.google.gson.JsonEle"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/LogTime.java",
"chars": 365,
"preview": "package rxhttp.wrapper.utils;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * User: ljx\n * Date: 2019-11-30\n * Time: 18:3"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/LogUtil.java",
"chars": 18465,
"preview": "package rxhttp.wrapper.utils;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimpo"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/PathEncoder.kt",
"chars": 2456,
"preview": "package rxhttp.wrapper.utils\n\nimport okio.Buffer\n\n\n/**\n * User: ljx\n * Date: 2021/10/24\n * Time: 21:25\n */\nprivate val H"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Speeder.kt",
"chars": 1017,
"preview": "package rxhttp.wrapper.utils\n\nimport java.util.concurrent.LinkedBlockingQueue\n\n/**\n * User: ljx\n * Date: 2024/6/16\n * Ti"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/TypeUtil.java",
"chars": 1039,
"preview": "package rxhttp.wrapper.utils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.ParameterizedType;\ni"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Uri.kt",
"chars": 2274,
"preview": "@file:JvmName(\"UriUtil\")\n\npackage rxhttp.wrapper.utils\n\nimport android.content.ContentResolver\nimport android.content.Co"
},
{
"path": "rxhttp/src/main/java/rxhttp/wrapper/utils/Utils.kt",
"chars": 4459,
"preview": "@file:JvmName(\"Utils\")\npackage rxhttp.wrapper.utils\n\nimport kotlinx.coroutines.suspendCancellableCoroutine\nimport okhttp"
},
{
"path": "rxhttp/src/main/java-templates/rxhttp/internal/RxHttpVersion.kt",
"chars": 158,
"preview": "@file:JvmName(\"RxHttpVersion\")\n\npackage rxhttp.internal\n\n/**\n * User: ljx\n * Date: 2020/5/17\n * Time: 18:29\n */\nconst va"
},
{
"path": "rxhttp/src/test/java/rxhttp/wrapper/entity/ParameterizedTypeImplTest.java",
"chars": 2886,
"preview": "package rxhttp.wrapper.entity;\n\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.lang.reflect.Parameterized"
},
{
"path": "rxhttp-annotation/build.gradle",
"chars": 235,
"preview": "plugins {\n id 'java-library'\n}\napply from: '../maven.gradle'\n\ndependencies {\n implementation fileTree(dir: 'libs',"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/Converter.java",
"chars": 412,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/DefaultDomain.java",
"chars": 316,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/Domain.java",
"chars": 404,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/OkClient.java",
"chars": 496,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/Param.java",
"chars": 312,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-annotation/src/main/java/rxhttp/wrapper/annotation/Parser.java",
"chars": 565,
"preview": "package rxhttp.wrapper.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimpo"
},
{
"path": "rxhttp-compiler/build.gradle",
"chars": 681,
"preview": "import org.jetbrains.kotlin.gradle.dsl.JvmTarget\n\nplugins {\n id 'org.jetbrains.kotlin.jvm'\n id 'kotlin-kapt'\n}\napp"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/Constants.kt",
"chars": 1039,
"preview": "package com.rxhttp.compiler\n\nimport com.squareup.javapoet.ArrayTypeName\nimport com.squareup.javapoet.ClassName\nimport co"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/KaptProcessor.kt",
"chars": 6701,
"preview": "package com.rxhttp.compiler\n\nimport com.rxhttp.compiler.kapt.BaseRxHttpGenerator\nimport com.rxhttp.compiler.kapt.ClassHe"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/KspProcessor.kt",
"chars": 5283,
"preview": "package com.rxhttp.compiler\n\nimport com.google.devtools.ksp.KspExperimental\nimport com.google.devtools.ksp.processing.Re"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/RxJavaVersion.kt",
"chars": 2569,
"preview": "package com.rxhttp.compiler\n\nimport com.rxhttp.compiler.common.versionCompare\n\n/**\n * RxJava 版本管理\n * User: ljx\n * Date: "
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/Variables.kt",
"chars": 164,
"preview": "package com.rxhttp.compiler\n\n/**\n * User: ljx\n * Date: 2021/11/23\n * Time: 17:38\n */\nlateinit var rxHttpPackage: String "
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/common/KtUtil.kt",
"chars": 7057,
"preview": "package com.rxhttp.compiler.common\n\nimport com.rxhttp.compiler.K_ARRAY_TYPE\nimport com.rxhttp.compiler.K_TYPE\nimport com"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/common/ObservableUtil.kt",
"chars": 21662,
"preview": "package com.rxhttp.compiler.common\n\nimport com.rxhttp.compiler.getClassPath\nimport com.rxhttp.compiler.rxHttpPackage\n\n/*"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/common/StringUtil.kt",
"chars": 1715,
"preview": "package com.rxhttp.compiler.common\n\nimport com.rxhttp.compiler.ksp.isVararg\nimport com.squareup.kotlinpoet.ParameterSpec"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/BaseRxHttpGenerator.kt",
"chars": 11735,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.getClassPath\nimport com.rxhttp.compiler.isDependenceRxJava\n"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/ClassHelper.kt",
"chars": 24465,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.common.getObservableClass\nimport com.rxhttp.compiler.isDepe"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/ConverterVisitor.kt",
"chars": 3104,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.rxhttpClass\nimport com.squareup.javapoet.ClassName\nimport c"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/DefaultDomainVisitor.kt",
"chars": 1693,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport "
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/DomainVisitor.kt",
"chars": 3102,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.rxhttpClass\nimport com.squareup.javapoet.ClassName\nimport c"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/OkClientVisitor.kt",
"chars": 3081,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.rxhttpClass\nimport com.squareup.javapoet.ClassName\nimport c"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/ParamsVisitor.kt",
"chars": 9252,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.common.joinToStringIndexed\nimport com.rxhttp.compiler.rxHtt"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/ParserVisitor.kt",
"chars": 14994,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.J_ARRAY_TYPE\nimport com.rxhttp.compiler.J_TYPE\nimport com.r"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/RxHttpExtensions.kt",
"chars": 8942,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.common.flapTypeParameterSpecTypes\nimport com.rxhttp.compile"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/RxHttpGenerator.kt",
"chars": 36913,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.RxHttp\nimport com.rxhttp.compiler.rxHttpPackage\nimport com."
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/RxHttpWrapper.kt",
"chars": 9505,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.rxHttpPackage\nimport com.rxhttp.compiler.rxhttpClass\nimport"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/Utils.kt",
"chars": 4195,
"preview": "package com.rxhttp.compiler.kapt\n\nimport com.rxhttp.compiler.J_ARRAY_TYPE\nimport com.rxhttp.compiler.J_TYPE\nimport com.s"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/maven/KaptRxJava2Processor.kt",
"chars": 309,
"preview": "package com.rxhttp.compiler.kapt.maven\n\nimport com.rxhttp.compiler.KaptProcessor\n\n/**\n * User: ljx\n * Date: 2020/8/8\n * "
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/kapt/maven/KaptRxJava3Processor.kt",
"chars": 307,
"preview": "package com.rxhttp.compiler.kapt.maven\n\nimport com.rxhttp.compiler.KaptProcessor\n\n/**\n * User: ljx\n * Date: 2020/8/8\n * "
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/BaseRxHttpGenerator.kt",
"chars": 10373,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.KspExperimental\nimport com.google.devtools.ksp.processin"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/ClassHelper.kt",
"chars": 993,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.processing.CodeGenerator\nimport com.google.devtools.ksp."
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/ConverterVisitor.kt",
"chars": 3814,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.KspExperimental\nimport com.google.devtools.ksp.getAnnota"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/DefaultDomainVisitor.kt",
"chars": 1761,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.processing.KSPLogger\nimport com.google.devtools.ksp.proc"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/DomainVisitor.kt",
"chars": 3861,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.KspExperimental\nimport com.google.devtools.ksp.getAnnota"
},
{
"path": "rxhttp-compiler/src/main/java/com/rxhttp/compiler/ksp/KClassHelper.kt",
"chars": 17336,
"preview": "package com.rxhttp.compiler.ksp\n\nimport com.google.devtools.ksp.processing.CodeGenerator\nimport com.google.devtools.ksp."
}
]
// ... and 30 more files (download for full content)
About this extraction
This page contains the full source code of the liujingxing/rxhttp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 230 files (760.0 KB), approximately 185.5k tokens, and a symbol index with 859 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.