Repository: jeasonlzy/okhttp-OkGo Branch: master Commit: e34c2fa150db Files: 276 Total size: 889.0 KB Directory structure: gitextract_01imco5q/ ├── .gitignore ├── LICENSE ├── README.md ├── appkey.jks ├── build.gradle ├── demo/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── assets/ │ │ └── srca.cer │ ├── java/ │ │ └── com/ │ │ └── lzy/ │ │ └── demo/ │ │ ├── GApp.java │ │ ├── MainActivity.java │ │ ├── PayFragment.java │ │ ├── WebActivity.java │ │ ├── base/ │ │ │ ├── BaseActivity.java │ │ │ ├── BaseDetailActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── BaseRecyclerAdapter.java │ │ │ ├── BaseRxDetailActivity.java │ │ │ ├── DividerItemDecoration.java │ │ │ └── MainFragment.java │ │ ├── callback/ │ │ │ ├── BitmapDialogCallback.java │ │ │ ├── DialogCallback.java │ │ │ ├── EncryptCallback.java │ │ │ ├── JsonCallback.java │ │ │ ├── JsonConvert.java │ │ │ └── StringDialogCallback.java │ │ ├── model/ │ │ │ ├── ApkModel.java │ │ │ ├── GankModel.java │ │ │ ├── GankResponse.java │ │ │ ├── ItemModel.java │ │ │ ├── LzyResponse.java │ │ │ ├── ServerModel.java │ │ │ └── SimpleResponse.java │ │ ├── okdownload/ │ │ │ ├── DesActivity.java │ │ │ ├── DownloadAdapter.java │ │ │ ├── DownloadAllActivity.java │ │ │ ├── DownloadFinishActivity.java │ │ │ ├── DownloadListActivity.java │ │ │ ├── DownloadingActivity.java │ │ │ ├── LogDownloadListener.java │ │ │ └── OkDownloadFragment.java │ │ ├── okgo/ │ │ │ ├── BitmapRequestActivity.java │ │ │ ├── CacheActivity.java │ │ │ ├── CommonActivity.java │ │ │ ├── CookieActivity.java │ │ │ ├── FormUploadActivity.java │ │ │ ├── HttpsActivity.java │ │ │ ├── JsonActivity.java │ │ │ ├── MethodActivity.java │ │ │ ├── OkGoFragment.java │ │ │ ├── RedirectActivity.java │ │ │ ├── SimpleDownloadActivity.java │ │ │ ├── SyncActivity.java │ │ │ ├── TestActivity.java │ │ │ └── UpActivity.java │ │ ├── okrx2/ │ │ │ ├── OkRx2Fragment.java │ │ │ ├── OkRxFragment.java │ │ │ ├── RxBitmapActivity.java │ │ │ ├── RxCacheActivity.java │ │ │ ├── RxCommonActivity.java │ │ │ ├── RxFileDownloadActivity.java │ │ │ ├── RxFormUploadActivity.java │ │ │ ├── RxRetrofitActivity.java │ │ │ ├── RxUtils.java │ │ │ └── ServerApi.java │ │ ├── okupload/ │ │ │ ├── LogUploadListener.java │ │ │ ├── OkUploadFragment.java │ │ │ ├── UploadAdapter.java │ │ │ ├── UploadAllActivity.java │ │ │ ├── UploadFinishActivity.java │ │ │ ├── UploadListActivity.java │ │ │ └── UploadingActivity.java │ │ ├── supercache/ │ │ │ ├── NewsAdapter.java │ │ │ ├── NewsCallback.java │ │ │ ├── NewsTabFragment.java │ │ │ └── SuperCacheActivity.java │ │ ├── ui/ │ │ │ ├── NumberProgressBar.java │ │ │ ├── ProgressPieView.java │ │ │ ├── SimpleViewBehavior.java │ │ │ └── TranslateUpDownBehavior.java │ │ └── utils/ │ │ ├── AnimHelper.java │ │ ├── ApkUtils.java │ │ ├── ColorUtils.java │ │ ├── Convert.java │ │ ├── GlideImageLoader.java │ │ ├── MD5Utils.java │ │ ├── PicassoImageLoader.java │ │ └── Urls.java │ └── res/ │ ├── drawable/ │ │ └── progress_bar_states.xml │ ├── layout/ │ │ ├── activity_base.xml │ │ ├── activity_bitmap_request.xml │ │ ├── activity_cache.xml │ │ ├── activity_cookie.xml │ │ ├── activity_custom_request.xml │ │ ├── activity_download_all.xml │ │ ├── activity_download_details.xml │ │ ├── activity_download_list.xml │ │ ├── activity_file_download.xml │ │ ├── activity_form_upload.xml │ │ ├── activity_https.xml │ │ ├── activity_main.xml │ │ ├── activity_method.xml │ │ ├── activity_recycler.xml │ │ ├── activity_redirect.xml │ │ ├── activity_rx_cache.xml │ │ ├── activity_rx_common.xml │ │ ├── activity_rx_file_download.xml │ │ ├── activity_rx_form_upload.xml │ │ ├── activity_rx_retrofit.xml │ │ ├── activity_super_cache.xml │ │ ├── activity_sync.xml │ │ ├── activity_test.xml │ │ ├── activity_up_text.xml │ │ ├── activity_upload_list.xml │ │ ├── activity_web.xml │ │ ├── fragment_pay.xml │ │ ├── include_data.xml │ │ ├── item_download_list.xml │ │ ├── item_download_manager.xml │ │ ├── item_main_list.xml │ │ ├── item_main_type.xml │ │ ├── item_news.xml │ │ ├── item_no_data.xml │ │ ├── item_refresh.xml │ │ └── item_upload_manager.xml │ └── values/ │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── jar/ │ ├── okgo-3.0.4.jar │ ├── okhttp-3.8.1.jar │ ├── okio-1.13.0.jar │ ├── okrx-1.0.2.jar │ ├── okrx2-2.0.2.jar │ └── okserver-2.0.5.jar ├── okgo/ │ ├── .gitignore │ ├── bintray.gradle │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── lzy/ │ └── okgo/ │ ├── OkGo.java │ ├── adapter/ │ │ ├── AdapterParam.java │ │ ├── CacheCall.java │ │ ├── Call.java │ │ ├── CallAdapter.java │ │ └── DefaultCallAdapter.java │ ├── cache/ │ │ ├── CacheEntity.java │ │ ├── CacheMode.java │ │ └── policy/ │ │ ├── BaseCachePolicy.java │ │ ├── CachePolicy.java │ │ ├── DefaultCachePolicy.java │ │ ├── FirstCacheRequestPolicy.java │ │ ├── NoCachePolicy.java │ │ ├── NoneCacheRequestPolicy.java │ │ └── RequestFailedCachePolicy.java │ ├── callback/ │ │ ├── AbsCallback.java │ │ ├── BitmapCallback.java │ │ ├── Callback.java │ │ ├── FileCallback.java │ │ └── StringCallback.java │ ├── convert/ │ │ ├── BitmapConvert.java │ │ ├── Converter.java │ │ ├── FileConvert.java │ │ └── StringConvert.java │ ├── cookie/ │ │ ├── CookieJarImpl.java │ │ ├── SerializableCookie.java │ │ └── store/ │ │ ├── CookieStore.java │ │ ├── DBCookieStore.java │ │ ├── MemoryCookieStore.java │ │ └── SPCookieStore.java │ ├── db/ │ │ ├── BaseDao.java │ │ ├── CacheManager.java │ │ ├── ColumnEntity.java │ │ ├── CookieManager.java │ │ ├── DBHelper.java │ │ ├── DBUtils.java │ │ ├── DownloadManager.java │ │ ├── TableEntity.java │ │ └── UploadManager.java │ ├── exception/ │ │ ├── CacheException.java │ │ ├── HttpException.java │ │ ├── OkGoException.java │ │ └── StorageException.java │ ├── https/ │ │ └── HttpsUtils.java │ ├── interceptor/ │ │ └── HttpLoggingInterceptor.java │ ├── model/ │ │ ├── HttpHeaders.java │ │ ├── HttpMethod.java │ │ ├── HttpParams.java │ │ ├── Priority.java │ │ ├── Progress.java │ │ ├── Response.java │ │ └── Result.java │ ├── request/ │ │ ├── DeleteRequest.java │ │ ├── GetRequest.java │ │ ├── HeadRequest.java │ │ ├── OptionsRequest.java │ │ ├── PatchRequest.java │ │ ├── PostRequest.java │ │ ├── PutRequest.java │ │ ├── TraceRequest.java │ │ └── base/ │ │ ├── BodyRequest.java │ │ ├── HasBody.java │ │ ├── NoBodyRequest.java │ │ ├── ProgressRequestBody.java │ │ └── Request.java │ └── utils/ │ ├── HeaderParser.java │ ├── HttpUtils.java │ ├── IOUtils.java │ └── OkLogger.java ├── okrx/ │ ├── .gitignore │ ├── bintray.gradle │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── lzy/ │ └── okrx/ │ ├── adapter/ │ │ ├── AnalysisParams.java │ │ ├── CompletableResponse.java │ │ ├── ObservableBody.java │ │ ├── ObservableResponse.java │ │ ├── ObservableResult.java │ │ ├── SingleBody.java │ │ ├── SingleResponse.java │ │ └── SingleResult.java │ └── subscribe/ │ ├── BodyOnSubscribe.java │ ├── CallArbiter.java │ ├── CallEnqueueOnSubscribe.java │ ├── CallExecuteOnSubscribe.java │ └── ResultOnSubscribe.java ├── okrx2/ │ ├── .gitignore │ ├── bintray.gradle │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── lzy/ │ └── okrx2/ │ ├── adapter/ │ │ ├── AnalysisParams.java │ │ ├── CompletableResponse.java │ │ ├── FlowableBody.java │ │ ├── FlowableResponse.java │ │ ├── FlowableResult.java │ │ ├── MaybeBody.java │ │ ├── MaybeResponse.java │ │ ├── MaybeResult.java │ │ ├── ObservableBody.java │ │ ├── ObservableResponse.java │ │ ├── ObservableResult.java │ │ ├── SingleBody.java │ │ ├── SingleResponse.java │ │ └── SingleResult.java │ └── observable/ │ ├── BodyObservable.java │ ├── CallEnqueueObservable.java │ ├── CallExecuteObservable.java │ └── ResultObservable.java ├── okserver/ │ ├── .gitignore │ ├── bintray.gradle │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── com/ │ └── lzy/ │ └── okserver/ │ ├── OkDownload.java │ ├── OkUpload.java │ ├── ProgressListener.java │ ├── download/ │ │ ├── DownloadListener.java │ │ ├── DownloadTask.java │ │ └── DownloadThreadPool.java │ ├── task/ │ │ ├── PriorityBlockingQueue.java │ │ ├── PriorityObject.java │ │ ├── PriorityRunnable.java │ │ └── XExecutor.java │ └── upload/ │ ├── UploadListener.java │ ├── UploadTask.java │ └── UploadThreadPool.java └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /.idea /screenshots /local.properties .DS_Store /build /captures libs/ ================================================ 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 2016 jeasonlzy(廖子尧) 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 ================================================ ![](http://7xss53.com1.z0.glb.clouddn.com/markdown/aqyyw.jpg) ## OkGo - 3.0 震撼来袭, 一个基于okhttp的标准RESTful风格的网络框架 > 工程结构全新优化 支持RxJava 支持RxJava2 支持自定义缓存策略 支持下载管理 支持上传管理 该库部分思想借鉴了以下项目: * [https://github.com/yanzhenjie/NoHttp](https://github.com/Y0LANDA/NoHttp) * [https://github.com/square/retrofit](https://github.com/square/retrofit) 在此特别感谢上述作者,喜欢原作的可以去使用原项目。同时欢迎大家下载体验本项目,如果使用过程中遇到什么问题,欢迎反馈。 ## 友情链接 本项目中使用的图片选择是我的另一个开源项目 > 完全仿微信的图片选择库,自带矩形图片裁剪和圆形图片裁剪功能,有需要的可以去下载使用。 附上地址:[https://github.com/jeasonlzy/ImagePicker](https://github.com/jeasonlzy/ImagePicker) 本项目中的九宫格控件也是我的开源项目 > 类似QQ空间,微信朋友圈,微博主页等,展示图片的九宫格控件,自动根据图片的数量确定图片大小和控件大小,使用Adapter模式设置图片,对外提供接口回调,使用接口加载图片,支持任意的图片加载框架如:Glide、ImageLoader、xUtils3、Picasso 等,支持点击图片全屏预览大图。 附上地址:[https://github.com/jeasonlzy/NineGridView](https://github.com/jeasonlzy/NineGridView) ## 联系方式 * email: liaojeason@126.com * QQ群: 489873144 Android 格调小窝(点击图标,可以直接加入,建议使用QQ群,邮箱使用较少,可能看的不及时) * 如果遇到问题欢迎在群里提问,个人能力也有限,希望一起学习一起进步。 ## 演示 ![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo13.gif)![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo8.gif)![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo11.gif)![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo9.gif)![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo10.gif)![image](https://github.com/jeasonlzy/Screenshots/blob/master/okgo/demo12.gif) ## 未来版本 ### [v3.1.x]版本 - 计划分离params参数的具体作用,分为paramsPath,paramsQuery和params,支持url路径动态替换 - 计划支持请求优先级,方便有些重要请求优先进行 - 计划支持自定义线程池,使用自己的线程池管理网络请求 ### [v3.2.x]版本 - 计划增加扩展库OkAnno,作用是让okgo支持注解方式请求,具体写法与Retrofit相似,但是更简单方便,也更强大,方便Retrofit用户平滑过渡到OkGo ### 其他功能暂时还没想出来,大家有想法的可以积极加群讨论,或者直接在issue里面提出你的想法,我会第一时间回复。 ## 使用 [![](https://img.shields.io/badge/API-14%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=14) [![](https://img.shields.io/badge/platform-android-brightgreen.svg)](https://developer.android.com/index.html) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/5b244560c35c445cbb00b9500b0c5d2a)](https://www.codacy.com/app/jeasonlzy/okhttp-OkGo?utm_source=github.com&utm_medium=referral&utm_content=jeasonlzy/okhttp-OkGo&utm_campaign=Badge_Grade) [![](https://img.shields.io/hexpm/l/plug.svg)](https://github.com/jeasonlzy/okhttp-OkGo/blob/master/LICENSE) [![](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-jeasonlzy-orange.svg)](https://github.com/jeasonlzy) [![](https://img.shields.io/badge/OkGo-v3.0.4-brightgreen.svg)](https://github.com/jeasonlzy/okhttp-OkGo) [![](https://img.shields.io/badge/OkRx-v1.0.2-brightgreen.svg)](https://github.com/jeasonlzy/okhttp-OkGo) [![](https://img.shields.io/badge/OkRx2-v2.0.2-brightgreen.svg)](https://github.com/jeasonlzy/okhttp-OkGo) [![](https://img.shields.io/badge/OkServer-v2.0.5-brightgreen.svg)](https://github.com/jeasonlzy/okhttp-OkGo) Android Studio用户 > 一般来说,只需要添加第一个okgo的核心包即可,其余的三个库根据自己的需要选择添加!!! ```java //必须使用 compile 'com.lzy.net:okgo:3.0.4' //以下三个选择添加,okrx和okrx2不能同时使用 compile 'com.lzy.net:okrx:1.0.2' compile 'com.lzy.net:okrx2:2.0.2' compile 'com.lzy.net:okserver:2.0.5' ``` Eclipse的用户(赶紧换AS吧),可以选择添加本项目根目录中 `/jar` 目录下的jar包: > 一般来说,至少需要okhttp、okio、okgo三个jar包,其余的三个扩展jar包根据自己的需要选择添加!!! 必须使用 > [okhttp-3.8.1.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okhttp-3.8.1.jar) [okio-1.13.0.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okio-1.13.0.jar) [okgo-3.0.4.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okgo-3.0.4.jar) 以下三个选择添加,okrx和okrx2不能同时使用 > [okrx-1.0.2.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okrx-1.0.2.jar) [okrx2-2.0.2.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okrx2-2.0.2.jar) [okserver-2.0.5.jar](https://raw.githubusercontent.com/jeasonlzy/okhttp-OkGo/master/jar/okserver-2.0.5.jar) ## 文档 ### 该项目的文档全部以Wiki的形式展示,wiki文档永远与最新版本的库保持同步,如果你发现文档的说明与你的写法不一样,那么请升级到最新版本,重要的事情说三遍 - [点我,点我,我是3.x文档,Wiki文档首页请猛戳这里](https://github.com/jeasonlzy/okhttp-OkGo/wiki) - [点我,点我,我是3.x文档,Wiki文档首页请猛戳这里](https://github.com/jeasonlzy/okhttp-OkGo/wiki) - [点我,点我,我是3.x文档,Wiki文档首页请猛戳这里](https://github.com/jeasonlzy/okhttp-OkGo/wiki) 如果你实在不愿意升级到3.x版本,[这里有2.x版本的文档,点击查看](https://github.com/jeasonlzy/okhttp-OkGo/tree/v2.1.4),注意:老版本库的问题将不在维护,所有bug会在最新版本修复,所以建议跟随最新版本的库。 [![](http://7xss53.com1.z0.glb.clouddn.com/markdown/w0ujl.jpg)](https://github.com/jeasonlzy/okhttp-OkGo/wiki) 如果遇到使用问题,解决办法如下: 1. 看上述文档中是否有相关描述 2. 看别人提的issues是否有你的问题,这里面有很多人的提问,[点击这里看别人的提问](https://github.com/jeasonlzy/okhttp-OkGo/issues?q=is%3Aissue+is%3Aclosed)。 3. 如果你感觉是bug,或者有疑问,也欢迎在issues里面提问,我每天都会认真解答,[点击这里提问](https://github.com/jeasonlzy/okhttp-OkGo/issues)。 4. 还有疑问,加入联系方式中的QQ群,大家一起讨论。 如果你不想编译项目,提供了apk供直接运行,方便查看效果,点击图标下载:[![](https://img.shields.io/badge/downloads-okgo__v3.0.4.apk-blue.svg)](http://7xss53.com1.z0.glb.clouddn.com/file/okgo_v3.0.4.apk) 本项目Demo使用的是我自己的服务器,有时候可能不稳定,网速比较慢时请耐心等待,尴尬呀。。 如果你想查看历史版本信息,请点击图标:[![](https://img.shields.io/badge/release-tags-ff69b4.svg)](https://github.com/jeasonlzy/okhttp-OkGo/releases) 如果你使用遇到了问题,首先请看控制台log,如果log无法看出问题,无法确定是该库的bug还是服务端的问题,建议抓包查看网络数据,[详细的抓包方法猛戳这里](https://github.com/jeasonlzy/okhttp-OkGo/wiki#网络抓包) ### 如果你觉得好,对你有过帮助,请给我一点打赏鼓励吧,一分也是爱呀! ![](https://ws2.sinaimg.cn/large/006tNbRwly1fgidan2gc9j30jg0a2wg6.jpg) ## 混淆 okgo, okrx, okrx2, okserver 所有代码均可以混淆,但是由于底层使用的是 okhttp,它不能混淆,所以只需要添加以下混淆代码就可以了 ```java #okhttp -dontwarn okhttp3.** -keep class okhttp3.**{*;} #okio -dontwarn okio.** -keep class okio.**{*;} ``` 当然如果你确实不需要混淆okgo的代码,可以继续添加以下代码 ```java #okgo -dontwarn com.lzy.okgo.** -keep class com.lzy.okgo.**{*;} #okrx -dontwarn com.lzy.okrx.** -keep class com.lzy.okrx.**{*;} #okrx2 -dontwarn com.lzy.okrx2.** -keep class com.lzy.okrx2.**{*;} #okserver -dontwarn com.lzy.okserver.** -keep class com.lzy.okserver.**{*;} ``` ## Licenses ``` Copyright 2016 jeasonlzy(廖子尧) 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: build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } } task clean(type: Delete) { delete rootProject.buildDir } ext { versionCode = 29 versionName_okgo = '3.0.4' versionName_okserver = '2.0.5' versionName_okrx = '1.0.2' versionName_okrx2 = '2.0.2' libMinSdkVersion = 14 appMinSdkVersion = 16 targetSdkVersion = 25 compileSdkVersion = 25 buildToolsVersion = '25.0.2' supportVersion = '25.3.1' } ================================================ FILE: demo/.gitignore ================================================ /build ================================================ FILE: demo/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { applicationId "com.lzy.demo" minSdkVersion rootProject.ext.appMinSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode rootProject.ext.versionCode versionName rootProject.ext.versionName_okgo } signingConfigs { appkey { keyAlias 'OkGo' keyPassword '111111' storeFile file('../appkey.jks') storePassword '111111' } } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' debuggable false signingConfig signingConfigs.appkey } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' debuggable true signingConfig signingConfigs.appkey } } productFlavors { miui { proguardFile './proguard-rules.pro' signingConfig signingConfigs.appkey } qihu360 { proguardFile './proguard-rules.pro' signingConfig signingConfigs.appkey } } lintOptions { abortOnError false } packagingOptions { exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' exclude 'META-INF/notice' exclude 'META-INF/notice.txt' exclude 'META-INF/license' exclude 'META-INF/license.txt' exclude 'META-INF/rxjava.properties' } } task makeApk { doLast { def versionName = rootProject.ext.versionName_okgo def appName = "okgo_v${versionName}.apk" copy { from "./build/outputs/apk/demo-miui-debug.apk" into "../" rename { appName } } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile "com.android.support:appcompat-v7:$supportVersion" compile "com.android.support:design:$supportVersion" compile "com.android.support:recyclerview-v7:$supportVersion" compile "com.android.support:cardview-v7:$supportVersion" compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:v2.0.7' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.jakewharton:butterknife:7.0.1' compile 'com.google.code.gson:gson:2.8.0' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.readystatesoftware.chuck:library:1.0.4' compile project(':okgo') compile project(':okrx') compile project(':okrx2') compile project(':okserver') // compile 'com.lzy.net:okgo:3.0.4' // compile 'com.lzy.net:okrx:1.0.2' // compile 'com.lzy.net:okrx2:2.0.2' // compile 'com.lzy.net:okserver:2.0.5' compile 'com.lzy.widget:ninegridview:0.2.1' compile 'com.lzy.widget:imagepicker:0.3.2' compile 'com.lzy.widget:view-core:0.2.1' } ================================================ FILE: demo/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in E:\Android\SDK/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # 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 *; #} #---------------------------------1.实体类--------------------------------- -keep class com.lzy.okhttpdemo.Bean.** { *; } #------------------------------------------------------------------------- #---------------------------------2.第三方包------------------------------- #okgo #-dontwarn com.lzy.okgo.** #-keep class com.lzy.okgo.**{*;} #okrx #-dontwarn com.lzy.okrx.** #-keep class com.lzy.okrx.**{*;} #okserver #-dontwarn com.lzy.okserver.** #-keep class com.lzy.okserver.**{*;} #okhttp -dontwarn okhttp3.** -keep class okhttp3.**{*;} -keepattributes SourceFile,LineNumberTable -keep class com.parse.*{ *; } -dontwarn com.parse.** -dontwarn com.squareup.picasso.** -keepclasseswithmembernames class * { native ; } #okio -dontwarn okio.** -keep class okio.**{*;} #rxjava -dontwarn sun.misc.** -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode; } #imagepicker -dontwarn com.lzy.imagepicker.** -keep class com.lzy.imagepicker.**{*;} #imagepicker -dontwarn com.lzy.widget.** -keep class com.lzy.widget.**{*;} #butterknife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* ; } -keepclasseswithmembernames class * { @butterknife.* ; } #gson -keep class sun.misc.Unsafe { *; } -keep class com.google.gson.stream.**{ *; } -keep class com.google.gson.examples.android.model.**{ *; } -keep class com.google.gson.**{ *;} #eventBus -keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe ; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { (java.lang.Throwable); } -keepclassmembers class ** { public void onEvent*(**); } #glide -keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } #log4j #-libraryjars log4j-1.2.17.jar -dontwarn org.apache.log4j.** -keep class org.apache.log4j.** { *;} #------------------------------------------------------------------------ #---------------------------------3.与js互相调用的类------------------------ #-keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface { # ; #} #------------------------------------------------------------------------ #---------------------------------4.反射相关的类和方法----------------------- #------------------------------------------------------------------------ #---------------------------------基本指令区------------------------------- #代码混淆的压缩比例,值在0-7之间 -optimizationpasses 5 #混淆后类名都为小写 -dontusemixedcaseclassnames #指定不去忽略非公共的库的类 -dontskipnonpubliclibraryclasses #指定不去忽略非公共的库的类的成员 -dontskipnonpubliclibraryclassmembers #不做预校验的操作 -dontpreverify #生成原类名和混淆后的类名的映射文件 -verbose -printmapping proguardMapping.txt #指定混淆是采用的算法 -optimizations !code/simplification/cast,!field/*,!class/merging/* #不混淆Annotation -keepattributes *Annotation*,InnerClasses #不混淆泛型 -keepattributes Signature #抛出异常时保留代码行号 -keepattributes SourceFile,LineNumberTable #------------------------------------------------------------------------ #-keep class XXXX 保留类名不变,也就是类名不混淆,而类中的成员名不保证。当然也可以是继承XXX类的所有类名不混淆 #-keepclasseswithmembers class XXXX 保留类名和成员名,当然也可以是类中特定方法 #---------------------------------默认保留区------------------------------- -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class * extends android.view.View -keep public class com.android.vending.licensing.ILicensingService -keep public class * extends android.support.** -keep public class * extends android.app.Fragment -dontwarn android.support.** -keep class android.support.** {*;} #自定义控件不要混淆 -keep public class * extends android.view.View {*;} #adapter不能混淆 -keep public class * extends android.widget.BaseAdapter {*;} #CusorAdapter不混淆 -keep public class * extends android.widget.CusorAdapter{*;} -keepclasseswithmembernames class * { native ; } -keepclassmembers class * extends android.app.Activity{ public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep public class * extends android.view.View{ *** get*(); void set*(***); public (android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } -keep class * extends java.util.ListResourceBundle { protected Object[][] getContents(); } -keepnames class * implements java.io.Serializable -keepclassmembers class * implements java.io.Serializable {*;} -keep class **.R$* {*;} -keepclassmembers class * { void *(**On*Event); } #---------------------------------------------------------------------------- #---------------------------------webview------------------------------------ -keepclassmembers class fqcn.of.javascript.interface.for.Webview { public *; } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); public boolean *(android.webkit.WebView, java.lang.String); } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView, jav.lang.String); } #---------------------------------------------------------------------------- ================================================ FILE: demo/src/main/AndroidManifest.xml ================================================ ================================================ FILE: demo/src/main/java/com/lzy/demo/GApp.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo; import android.app.Application; import com.lzy.okgo.OkGo; import com.lzy.okgo.cache.CacheEntity; import com.lzy.okgo.cache.CacheMode; import com.lzy.okgo.cookie.CookieJarImpl; import com.lzy.okgo.cookie.store.DBCookieStore; import com.lzy.okgo.https.HttpsUtils; import com.lzy.okgo.interceptor.HttpLoggingInterceptor; import com.lzy.okgo.model.HttpHeaders; import com.lzy.okgo.model.HttpParams; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; /** * ================================================ * 作 者:廖子尧 github 地址 https://github.com/jeasonlzy/ * 版 本:1.0 * 创建日期:2015/9/23 * 描 述: * 修订历史: * ================================================ */ public class GApp extends Application { @Override public void onCreate() { super.onCreate(); // System.setProperty("http.proxyHost", "192.168.1.104"); //个人测试网络时用的,删掉即可 // System.setProperty("http.proxyPort", "8888"); initOkGo(); } private void initOkGo() { //---------这里给出的是示例代码,告诉你可以这么传,实际使用的时候,根据需要传,不需要就不传-------------// HttpHeaders headers = new HttpHeaders(); headers.put("commonHeaderKey1", "commonHeaderValue1"); //header不支持中文,不允许有特殊字符 headers.put("commonHeaderKey2", "commonHeaderValue2"); HttpParams params = new HttpParams(); params.put("commonParamsKey1", "commonParamsValue1"); //param支持中文,直接传,不要自己编码 params.put("commonParamsKey2", "这里支持中文参数"); //----------------------------------------------------------------------------------------// OkHttpClient.Builder builder = new OkHttpClient.Builder(); //log相关 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo"); loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY); //log打印级别,决定了log显示的详细程度 loggingInterceptor.setColorLevel(Level.INFO); //log颜色级别,决定了log在控制台显示的颜色 builder.addInterceptor(loggingInterceptor); //添加OkGo默认debug日志 //第三方的开源库,使用通知显示当前请求的log,不过在做文件下载的时候,这个库好像有问题,对文件判断不准确 //builder.addInterceptor(new ChuckInterceptor(this)); //超时时间设置,默认60秒 builder.readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); //全局的读取超时时间 builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); //全局的写入超时时间 builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); //全局的连接超时时间 //自动管理cookie(或者叫session的保持),以下几种任选其一就行 //builder.cookieJar(new CookieJarImpl(new SPCookieStore(this))); //使用sp保持cookie,如果cookie不过期,则一直有效 builder.cookieJar(new CookieJarImpl(new DBCookieStore(this))); //使用数据库保持cookie,如果cookie不过期,则一直有效 //builder.cookieJar(new CookieJarImpl(new MemoryCookieStore())); //使用内存保持cookie,app退出后,cookie消失 //https相关设置,以下几种方案根据需要自己设置 //方法一:信任所有证书,不安全有风险 HttpsUtils.SSLParams sslParams1 = HttpsUtils.getSslSocketFactory(); //方法二:自定义信任规则,校验服务端证书 HttpsUtils.SSLParams sslParams2 = HttpsUtils.getSslSocketFactory(new SafeTrustManager()); //方法三:使用预埋证书,校验服务端证书(自签名证书) //HttpsUtils.SSLParams sslParams3 = HttpsUtils.getSslSocketFactory(getAssets().open("srca.cer")); //方法四:使用bks证书和密码管理客户端证书(双向认证),使用预埋证书,校验服务端证书(自签名证书) //HttpsUtils.SSLParams sslParams4 = HttpsUtils.getSslSocketFactory(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer")); builder.sslSocketFactory(sslParams1.sSLSocketFactory, sslParams1.trustManager); //配置https的域名匹配规则,详细看demo的初始化介绍,不需要就不要加入,使用不当会导致https握手失败 builder.hostnameVerifier(new SafeHostnameVerifier()); // 其他统一的配置 // 详细说明看GitHub文档:https://github.com/jeasonlzy/ OkGo.getInstance().init(this) //必须调用初始化 .setOkHttpClient(builder.build()) //建议设置OkHttpClient,不设置会使用默认的 .setCacheMode(CacheMode.NO_CACHE) //全局统一缓存模式,默认不使用缓存,可以不传 .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE) //全局统一缓存时间,默认永不过期,可以不传 .setRetryCount(3) //全局统一超时重连次数,默认为三次,那么最差的情况会请求4次(一次原始请求,三次重连请求),不需要可以设置为0 .addCommonHeaders(headers) //全局公共头 .addCommonParams(params); //全局公共参数 } /** * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 重要的事情说三遍,以下代码不要直接使用 */ private class SafeTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { for (X509Certificate certificate : chain) { certificate.checkValidity(); //检查证书是否过期,签名是否通过等 } } catch (Exception e) { throw new CertificateException(e); } } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } /** * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 这里只是我谁便写的认证规则,具体每个业务是否需要验证,以及验证规则是什么,请与服务端或者leader确定 * 重要的事情说三遍,以下代码不要直接使用 */ private class SafeHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { //验证主机名是否匹配 //return hostname.equals("server.jeasonlzy.com"); return true; } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/MainActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; import android.util.Pair; import android.view.View; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.okdownload.OkDownloadFragment; import com.lzy.demo.okgo.OkGoFragment; import com.lzy.demo.okrx2.OkRx2Fragment; import com.lzy.demo.okrx2.OkRxFragment; import com.lzy.demo.okupload.OkUploadFragment; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class MainActivity extends BaseActivity { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.viewPager) ViewPager viewPager; @Bind(R.id.tab) TabLayout tab; private List> items; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initToolBar(toolbar, false, ""); items = new ArrayList<>(); items.add(new Pair("OkGo", new OkGoFragment())); items.add(new Pair("打赏", new PayFragment())); items.add(new Pair("OkRx2", new OkRx2Fragment())); items.add(new Pair("OkRx", new OkRxFragment())); items.add(new Pair("OkDownload", new OkDownloadFragment())); items.add(new Pair("OkUpload", new OkUploadFragment())); viewPager.setAdapter(new MainAdapter(getSupportFragmentManager())); tab.setupWithViewPager(viewPager); } @OnClick(R.id.fab) public void fab(View view) { WebActivity.runActivity(this, "我的Github,欢迎star", "https://github.com/jeasonlzy"); } @Override protected boolean translucentStatusBar() { return true; } private class MainAdapter extends FragmentPagerAdapter { MainAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return items.get(position).second; } @Override public int getCount() { return items.size(); } @Override public CharSequence getPageTitle(int position) { return items.get(position).first; } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/PayFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.lzy.demo.base.BaseFragment; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class PayFragment extends BaseFragment { @Override protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_pay, container, false); } @Override protected void initData() { } } ================================================ FILE: demo/src/main/java/com/lzy/demo/WebActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import com.lzy.demo.base.BaseActivity; import butterknife.Bind; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class WebActivity extends BaseActivity { public final static String URL = "url"; public final static String TITLE = "title"; @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.pb) ProgressBar pb; @Bind(R.id.webView) WebView webView; public static void runActivity(Context context, String title, String url) { Intent intent = new Intent(context, WebActivity.class); intent.putExtra(URL, url); intent.putExtra(TITLE, title); context.startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web); String url = getIntent().getStringExtra(URL); String title = getIntent().getStringExtra(TITLE); initToolBar(toolbar, true, title); pb.setMax(100); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setSupportZoom(true); webView.getSettings().setBuiltInZoomControls(true); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { pb.setProgress(newProgress); if (newProgress >= 100) { pb.setVisibility(View.GONE); } } }); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }); webView.loadUrl(url); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/BaseActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.app.ProgressDialog; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.support.annotation.LayoutRes; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.TypedValue; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.lzy.demo.R; import com.lzy.imagepicker.view.SystemBarTintManager; import butterknife.ButterKnife; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public abstract class BaseActivity extends AppCompatActivity { @SuppressWarnings("unchecked") public T findView(int id) { return (T) findViewById(id); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initSystemBarTint(); } @Override public void setContentView(@LayoutRes int layoutResID) { super.setContentView(layoutResID); ButterKnife.bind(this); } @Override public void setContentView(View view) { super.setContentView(view); ButterKnife.bind(this); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { super.setContentView(view, params); ButterKnife.bind(this); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home:// 点击返回图标事件 finish(); default: return super.onOptionsItemSelected(item); } } /** 子类可以重写改变状态栏颜色 */ protected int setStatusBarColor() { return getColorPrimary(); } /** 子类可以重写决定是否使用透明状态栏 */ protected boolean translucentStatusBar() { return false; } /** 设置状态栏颜色 */ protected void initSystemBarTint() { Window window = getWindow(); if (translucentStatusBar()) { // 设置状态栏全透明 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } return; } // 沉浸式状态栏 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0以上使用原生方法 window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(setStatusBarColor()); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //4.4-5.0使用三方工具类,有些4.4的手机有问题,这里为演示方便,不使用沉浸式 // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); SystemBarTintManager tintManager = new SystemBarTintManager(this); tintManager.setStatusBarTintEnabled(true); tintManager.setStatusBarTintColor(setStatusBarColor()); } } /** 获取主题色 */ public int getColorPrimary() { TypedValue typedValue = new TypedValue(); getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); return typedValue.data; } /** 获取深主题色 */ public int getDarkColorPrimary() { TypedValue typedValue = new TypedValue(); getTheme().resolveAttribute(R.attr.colorPrimaryDark, typedValue, true); return typedValue.data; } /** 初始化 Toolbar */ public void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled, String title) { toolbar.setTitle(title); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(homeAsUpEnabled); } public void initToolBar(Toolbar toolbar, boolean homeAsUpEnabled, int resTitle) { initToolBar(toolbar, homeAsUpEnabled, getString(resTitle)); } public void showToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } private ProgressDialog dialog; public void showLoading() { if (dialog != null && dialog.isShowing()) return; dialog = new ProgressDialog(this); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setCanceledOnTouchOutside(false); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setMessage("请求网络中..."); dialog.show(); } public void dismissLoading() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } public void displayImage(String url, ImageView imageView) { Glide.with(getApplicationContext())// .load(url)// .error(R.mipmap.ic_launcher)// .into(imageView); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/BaseDetailActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.FrameLayout; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.utils.Convert; import com.lzy.okgo.model.Response; import java.io.File; import java.util.List; import java.util.Map; import java.util.Set; import okhttp3.Call; import okhttp3.Headers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public abstract class BaseDetailActivity extends BaseActivity { protected ActionBar actionBar; protected TextView requestState; protected TextView requestHeaders; protected TextView responseData; protected TextView responseHeader; protected FrameLayout rootContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayShowTitleEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayShowHomeEnabled(true); } getDelegate().setContentView(R.layout.activity_base); Window window = getWindow(); requestState = (TextView) window.findViewById(R.id.requestState); requestHeaders = (TextView) window.findViewById(R.id.requestHeaders); responseData = (TextView) window.findViewById(R.id.responseData); responseHeader = (TextView) window.findViewById(R.id.responseHeader); rootContent = (FrameLayout) window.findViewById(R.id.content); onActivityCreate(savedInstanceState); } protected abstract void onActivityCreate(Bundle savedInstanceState); @Override public void setTitle(CharSequence title) { if (actionBar != null) actionBar.setTitle(title); } @Override public void setTitle(int titleId) { if (actionBar != null) actionBar.setTitle(titleId); } @Override public View findViewById(int id) { return rootContent.findViewById(id); } private void clearContentView() { rootContent.removeAllViews(); } @Override public void setContentView(int layoutResID) { clearContentView(); getLayoutInflater().inflate(layoutResID, rootContent, true); } @Override public void setContentView(View view) { clearContentView(); rootContent.addView(view); } @Override public void setContentView(View view, ViewGroup.LayoutParams params) { clearContentView(); rootContent.addView(view, params); } protected void handleResponse(T data) { Response response = new Response<>(); response.setBody(data); handleResponse(response); } protected void handleResponse(Response response) { StringBuilder sb; Call call = response.getRawCall(); if (call != null) { requestState.setText("请求成功 请求方式:" + call.request().method() + "\n" + "url:" + call.request().url()); Headers requestHeadersString = call.request().headers(); Set requestNames = requestHeadersString.names(); sb = new StringBuilder(); for (String name : requestNames) { sb.append(name).append(" : ").append(requestHeadersString.get(name)).append("\n"); } requestHeaders.setText(sb.toString()); } else { requestState.setText("--"); requestHeaders.setText("--"); } T body = response.body(); if (body == null) { responseData.setText("--"); } else { if (body instanceof String) { responseData.setText((String) body); } else if (body instanceof List) { sb = new StringBuilder(); List list = (List) body; for (Object obj : list) { sb.append(obj.toString()).append("\n"); } responseData.setText(sb.toString()); } else if (body instanceof Set) { sb = new StringBuilder(); Set set = (Set) body; for (Object obj : set) { sb.append(obj.toString()).append("\n"); } responseData.setText(sb.toString()); } else if (body instanceof Map) { sb = new StringBuilder(); Map map = (Map) body; Set keySet = map.keySet(); for (Object key : keySet) { sb.append(key.toString()).append(" : ").append(map.get(key)).append("\n"); } responseData.setText(sb.toString()); } else if (body instanceof File) { File file = (File) body; responseData.setText("数据内容即为文件内容\n下载文件路径:" + file.getAbsolutePath()); } else if (body instanceof Bitmap) { responseData.setText("图片的内容即为数据"); } else { responseData.setText(Convert.formatJson(body)); } } okhttp3.Response rawResponse = response.getRawResponse(); if (rawResponse != null) { Headers responseHeadersString = rawResponse.headers(); Set names = responseHeadersString.names(); sb = new StringBuilder(); sb.append("url : ").append(rawResponse.request().url()).append("\n\n"); sb.append("stateCode : ").append(rawResponse.code()).append("\n"); for (String name : names) { sb.append(name).append(" : ").append(responseHeadersString.get(name)).append("\n"); } responseHeader.setText(sb.toString()); } else { responseHeader.setText("--"); } } protected void handleError() { Response response = new Response<>(); handleResponse(response); } protected void handleError(Response response) { if (response == null) return; if (response.getException() != null) response.getException().printStackTrace(); StringBuilder sb; Call call = response.getRawCall(); if (call != null) { requestState.setText("请求失败 请求方式:" + call.request().method() + "\n" + "url:" + call.request().url()); Headers requestHeadersString = call.request().headers(); Set requestNames = requestHeadersString.names(); sb = new StringBuilder(); for (String name : requestNames) { sb.append(name).append(" : ").append(requestHeadersString.get(name)).append("\n"); } requestHeaders.setText(sb.toString()); } else { requestState.setText("--"); requestHeaders.setText("--"); } responseData.setText("--"); okhttp3.Response rawResponse = response.getRawResponse(); if (rawResponse != null) { Headers responseHeadersString = rawResponse.headers(); Set names = responseHeadersString.names(); sb = new StringBuilder(); sb.append("stateCode : ").append(rawResponse.code()).append("\n"); for (String name : names) { sb.append(name).append(" : ").append(responseHeadersString.get(name)).append("\n"); } responseHeader.setText(sb.toString()); } else { responseHeader.setText("--"); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/BaseFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; /** * 若把初始化内容放到initData实现,就是采用Lazy方式加载的Fragment * 若不需要Lazy加载则initData方法内留空,初始化内容放到initViews即可 * - * -注1: 如果是与ViewPager一起使用,调用的是setUserVisibleHint。 * ------可以调用mViewPager.setOffscreenPageLimit(size),若设置了该属性 则viewpager会缓存指定数量的Fragment * -注2: 如果是通过FragmentTransaction的show和hide的方法来控制显示,调用的是onHiddenChanged. * -注3: 针对初始就show的Fragment 为了触发onHiddenChanged事件 达到lazy效果 需要先hide再show */ /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public abstract class BaseFragment extends Fragment { protected String fragmentTitle; //fragment标题 private boolean isVisible; //是否可见状态 private boolean isPrepared; //标志位,View已经初始化完成。 private boolean isFirstLoad = true; //是否第一次加载 protected LayoutInflater inflater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.inflater = inflater; isFirstLoad = true; View view = initView(inflater, container, savedInstanceState); isPrepared = true; lazyLoad(); return view; } /** 如果是与ViewPager一起使用,调用的是setUserVisibleHint */ @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (getUserVisibleHint()) { isVisible = true; onVisible(); } else { isVisible = false; onInvisible(); } } /** * 如果是通过FragmentTransaction的show和hide的方法来控制显示,调用的是onHiddenChanged. * 若是初始就show的Fragment 为了触发该事件 需要先hide再show */ @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); if (!hidden) { isVisible = true; onVisible(); } else { isVisible = false; onInvisible(); } } protected void onVisible() { lazyLoad(); } protected void onInvisible() { } protected void lazyLoad() { if (!isPrepared || !isVisible || !isFirstLoad) { return; } isFirstLoad = false; initData(); } protected abstract View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); protected abstract void initData(); public String getTitle() { return TextUtils.isEmpty(fragmentTitle) ? "" : fragmentTitle; } public void setTitle(String title) { fragmentTitle = title; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/BaseRecyclerAdapter.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter { protected Context mContext; protected List mDatas; protected LayoutInflater inflater; public BaseRecyclerAdapter(Context context) { this.mContext = context; this.mDatas = new ArrayList<>(); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public BaseRecyclerAdapter(Context context, List datas) { if (datas == null) datas = new ArrayList<>(); this.mContext = context; this.mDatas = datas; inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public BaseRecyclerAdapter(Context context, T[] datas) { this.mContext = context; this.mDatas = new ArrayList(); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); Collections.addAll(mDatas, datas); } @Override public int getItemCount() { return mDatas == null ? 0 : mDatas.size(); } /** 更新数据,替换原有数据 */ public void updateItems(List items) { mDatas = items; notifyDataSetChanged(); } /** 插入一条数据 */ public void addItem(T item) { mDatas.add(0, item); notifyItemInserted(0); } /** 插入一条数据 */ public void addItem(T item, int position) { position = Math.min(position, mDatas.size()); mDatas.add(position, item); notifyItemInserted(position); } /** 在列表尾添加一串数据 */ public void addItems(List items) { int start = mDatas.size(); mDatas.addAll(items); notifyItemRangeChanged(start, items.size()); } /** 移除一条数据 */ public void removeItem(int position) { if (position > mDatas.size() - 1) { return; } mDatas.remove(position); notifyItemRemoved(position); } /** 移除一条数据 */ public void removeItem(T item) { int position = 0; ListIterator iterator = mDatas.listIterator(); while (iterator.hasNext()) { T next = iterator.next(); if (next == item) { iterator.remove(); notifyItemRemoved(position); } position++; } } /** 清除所有数据 */ public void removeAllItems() { mDatas.clear(); notifyDataSetChanged(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/BaseRxDetailActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/10/1 * 描 述:统一管理所有的订阅生命周期 * 修订历史: * ================================================ */ public abstract class BaseRxDetailActivity extends BaseDetailActivity { private CompositeDisposable compositeDisposable; public void addDisposable(Disposable disposable) { if (compositeDisposable == null) { compositeDisposable = new CompositeDisposable(); } compositeDisposable.add(disposable); } public void dispose() { if (compositeDisposable != null) compositeDisposable.dispose(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/DividerItemDecoration.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; /** * ================================================ * 作 者:jeasonlzy(廖子尧) * 版 本:1.0 * 创建日期:2016/4/7 * 描 述:我的Github地址 https://github.com/jeasonlzy * 修订历史: * ================================================ */ public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/base/MainFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.base; import android.content.Context; import android.graphics.Color; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.lzy.demo.R; import com.lzy.demo.model.ItemModel; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public abstract class MainFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { @Bind(R.id.refreshLayout) SwipeRefreshLayout refreshLayout; @Bind(R.id.recyclerView) RecyclerView recyclerView; protected Context context; private MainAdapter adapter; @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } @Override protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.item_refresh, container, false); ButterKnife.bind(this, view); return view; } @Override public void onRefresh() { setRefreshing(false); } @Override public void onLoadMoreRequested() { refreshLayout.postDelayed(new Runnable() { @Override public void run() { adapter.loadComplete(); } }, 500); } @Override protected void initData() { List items = new ArrayList<>(); fillData(items); adapter = new MainAdapter(items); adapter.openLoadAnimation(BaseQuickAdapter.SCALEIN); adapter.isFirstOnly(false); adapter.setOnLoadMoreListener(this); refreshLayout.setColorSchemeColors(Color.RED, Color.BLUE, Color.GREEN); refreshLayout.setOnRefreshListener(this); recyclerView.setLayoutManager(new LinearLayoutManager(context)); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addItemDecoration(new DividerItemDecoration(context, LinearLayoutManager.VERTICAL)); recyclerView.setAdapter(adapter); } public abstract void fillData(List items); public abstract void onItemClick(int position); private class MainAdapter extends BaseQuickAdapter { MainAdapter(List data) { super(R.layout.item_main_list, data); } @Override protected void convert(final BaseViewHolder baseViewHolder, ItemModel itemModel) { baseViewHolder.setText(R.id.title, itemModel.title); baseViewHolder.setText(R.id.des, itemModel.des); baseViewHolder.getConvertView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClick(baseViewHolder.getAdapterPosition()); } }); } } public void setRefreshing(final boolean refreshing) { refreshLayout.post(new Runnable() { @Override public void run() { refreshLayout.setRefreshing(refreshing); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/BitmapDialogCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.view.Window; import com.lzy.okgo.callback.BitmapCallback; import com.lzy.okgo.request.base.Request; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2016/1/14 * 描 述:请求图图片的时候显示对话框 * 修订历史: * ================================================ */ public abstract class BitmapDialogCallback extends BitmapCallback { private ProgressDialog dialog; public BitmapDialogCallback(Activity activity) { super(1000, 1000); dialog = new ProgressDialog(activity); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setCanceledOnTouchOutside(false); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setMessage("请求网络中..."); } @Override public void onStart(Request request) { if (dialog != null && !dialog.isShowing()) { dialog.show(); } } @Override public void onFinish() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/DialogCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import android.app.Activity; import android.app.ProgressDialog; import android.view.Window; import com.lzy.okgo.request.base.Request; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2016/1/14 * 描 述:对于网络请求是否需要弹出进度对话框 * 修订历史: * ================================================ */ public abstract class DialogCallback extends JsonCallback { private ProgressDialog dialog; private void initDialog(Activity activity) { dialog = new ProgressDialog(activity); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setCanceledOnTouchOutside(false); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setMessage("请求网络中..."); } public DialogCallback(Activity activity) { super(); initDialog(activity); } @Override public void onStart(Request request) { if (dialog != null && !dialog.isShowing()) { dialog.show(); } } @Override public void onFinish() { //网络请求结束后关闭对话框 if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/EncryptCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import com.lzy.demo.utils.MD5Utils; import com.lzy.okgo.model.HttpParams; import com.lzy.okgo.request.base.Request; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.TreeMap; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/11 * 描 述: * 修订历史: * ================================================ */ public abstract class EncryptCallback extends JsonCallback { private static final Random RANDOM = new Random(); private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyz"; @Override public void onStart(Request request) { super.onStart(request); //以下是示例加密代码,根据自己的业务需求和服务器的配合,算法自行决定,这里只是demo,不能用于商业项目 sign(request.getParams()); } /** * 针对URL进行签名,关于这几个参数的作用,详细请看 * http://www.cnblogs.com/bestzrz/archive/2011/09/03/2164620.html */ private void sign(HttpParams params) { params.put("nonce", getRndStr(6 + RANDOM.nextInt(8))); params.put("timestamp", "" + (System.currentTimeMillis() / 1000L)); StringBuilder sb = new StringBuilder(); Map map = new HashMap<>(); for (Map.Entry> entry : params.urlParamsMap.entrySet()) { map.put(entry.getKey(), entry.getValue().get(0)); } for (Map.Entry entry : getSortedMapByKey(map).entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } sb.delete(sb.length() - 1, sb.length()); String sign = MD5Utils.encode(sb.toString()); params.put("sign", sign); } /** 获取随机数 */ private String getRndStr(int length) { StringBuilder sb = new StringBuilder(); char ch; for (int i = 0; i < length; i++) { ch = CHARS.charAt(RANDOM.nextInt(CHARS.length())); sb.append(ch); } return sb.toString(); } /** 按照key的自然顺序进行排序,并返回 */ private Map getSortedMapByKey(Map map) { Comparator comparator = new Comparator() { @Override public int compare(String lhs, String rhs) { return lhs.compareTo(rhs); } }; Map treeMap = new TreeMap<>(comparator); for (Map.Entry entry : map.entrySet()) { treeMap.put(entry.getKey(), entry.getValue()); } return treeMap; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/JsonCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import com.lzy.okgo.callback.AbsCallback; import com.lzy.okgo.request.base.Request; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Response; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2016/1/14 * 描 述:默认将返回的数据解析成需要的Bean,可以是 BaseBean,String,List,Map * 修订历史: * ================================================ */ public abstract class JsonCallback extends AbsCallback { private Type type; private Class clazz; public JsonCallback() { } public JsonCallback(Type type) { this.type = type; } public JsonCallback(Class clazz) { this.clazz = clazz; } @Override public void onStart(Request request) { super.onStart(request); // 主要用于在所有请求之前添加公共的请求头或请求参数 // 例如登录授权的 token // 使用的设备信息 // 可以随意添加,也可以什么都不传 // 还可以在这里对所有的参数进行加密,均在这里实现 request.headers("header1", "HeaderValue1")// .params("params1", "ParamsValue1")// .params("token", "3215sdf13ad1f65asd4f3ads1f"); } /** * 该方法是子线程处理,不能做ui相关的工作 * 主要作用是解析网络返回的 response 对象,生产onSuccess回调中需要的数据对象 * 这里的解析工作不同的业务逻辑基本都不一样,所以需要自己实现,以下给出的时模板代码,实际使用根据需要修改 */ @Override public T convertResponse(Response response) throws Throwable { // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 //详细自定义的原理和文档,看这里: https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback if (type == null) { if (clazz == null) { Type genType = getClass().getGenericSuperclass(); type = ((ParameterizedType) genType).getActualTypeArguments()[0]; } else { JsonConvert convert = new JsonConvert<>(clazz); return convert.convertResponse(response); } } JsonConvert convert = new JsonConvert<>(type); return convert.convertResponse(response); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/JsonConvert.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import com.google.gson.stream.JsonReader; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.SimpleResponse; import com.lzy.demo.utils.Convert; import com.lzy.okgo.convert.Converter; import org.json.JSONArray; import org.json.JSONObject; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Response; import okhttp3.ResponseBody; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class JsonConvert implements Converter { private Type type; private Class clazz; public JsonConvert() { } public JsonConvert(Type type) { this.type = type; } public JsonConvert(Class clazz) { this.clazz = clazz; } /** * 该方法是子线程处理,不能做ui相关的工作 * 主要作用是解析网络返回的 response 对象,生成onSuccess回调中需要的数据对象 * 这里的解析工作不同的业务逻辑基本都不一样,所以需要自己实现,以下给出的时模板代码,实际使用根据需要修改 */ @Override public T convertResponse(Response response) throws Throwable { // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 // 重要的事情说三遍,不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 // 如果你对这里的代码原理不清楚,可以看这里的详细原理说明: https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback // 如果你对这里的代码原理不清楚,可以看这里的详细原理说明: https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback // 如果你对这里的代码原理不清楚,可以看这里的详细原理说明: https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback if (type == null) { if (clazz == null) { // 如果没有通过构造函数传进来,就自动解析父类泛型的真实类型(有局限性,继承后就无法解析到) Type genType = getClass().getGenericSuperclass(); type = ((ParameterizedType) genType).getActualTypeArguments()[0]; } else { return parseClass(response, clazz); } } if (type instanceof ParameterizedType) { return parseParameterizedType(response, (ParameterizedType) type); } else if (type instanceof Class) { return parseClass(response, (Class) type); } else { return parseType(response, type); } } private T parseClass(Response response, Class rawType) throws Exception { if (rawType == null) return null; ResponseBody body = response.body(); if (body == null) return null; JsonReader jsonReader = new JsonReader(body.charStream()); if (rawType == String.class) { //noinspection unchecked return (T) body.string(); } else if (rawType == JSONObject.class) { //noinspection unchecked return (T) new JSONObject(body.string()); } else if (rawType == JSONArray.class) { //noinspection unchecked return (T) new JSONArray(body.string()); } else { T t = Convert.fromJson(jsonReader, rawType); response.close(); return t; } } private T parseType(Response response, Type type) throws Exception { if (type == null) return null; ResponseBody body = response.body(); if (body == null) return null; JsonReader jsonReader = new JsonReader(body.charStream()); // 泛型格式如下: new JsonCallback<任意JavaBean>(this) T t = Convert.fromJson(jsonReader, type); response.close(); return t; } private T parseParameterizedType(Response response, ParameterizedType type) throws Exception { if (type == null) return null; ResponseBody body = response.body(); if (body == null) return null; JsonReader jsonReader = new JsonReader(body.charStream()); Type rawType = type.getRawType(); // 泛型的实际类型 Type typeArgument = type.getActualTypeArguments()[0]; // 泛型的参数 if (rawType != LzyResponse.class) { // 泛型格式如下: new JsonCallback<外层BaseBean<内层JavaBean>>(this) T t = Convert.fromJson(jsonReader, type); response.close(); return t; } else { if (typeArgument == Void.class) { // 泛型格式如下: new JsonCallback>(this) SimpleResponse simpleResponse = Convert.fromJson(jsonReader, SimpleResponse.class); response.close(); //noinspection unchecked return (T) simpleResponse.toLzyResponse(); } else { // 泛型格式如下: new JsonCallback>(this) LzyResponse lzyResponse = Convert.fromJson(jsonReader, type); response.close(); int code = lzyResponse.code; //这里的0是以下意思 //一般来说服务器会和客户端约定一个数表示成功,其余的表示失败,这里根据实际情况修改 if (code == 0) { //noinspection unchecked return (T) lzyResponse; } else if (code == 104) { throw new IllegalStateException("用户授权信息无效"); } else if (code == 105) { throw new IllegalStateException("用户收取信息已过期"); } else { //直接将服务端的错误信息抛出,onError中可以获取 throw new IllegalStateException("错误代码:" + code + ",错误信息:" + lzyResponse.msg); } } } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/callback/StringDialogCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.callback; import android.app.Activity; import android.app.ProgressDialog; import android.view.Window; import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.request.base.Request; /** * ================================================ * 作 者:jeasonlzy(廖子尧) * 版 本:1.0 * 创建日期:2016/4/8 * 描 述:我的Github地址 https://github.com/jeasonlzy * 修订历史: * ================================================ */ public abstract class StringDialogCallback extends StringCallback { private ProgressDialog dialog; public StringDialogCallback(Activity activity) { dialog = new ProgressDialog(activity); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setCanceledOnTouchOutside(false); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setMessage("请求网络中..."); } @Override public void onStart(Request request) { if (dialog != null && !dialog.isShowing()) { dialog.show(); } } @Override public void onFinish() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/ApkModel.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; import java.util.Random; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class ApkModel implements Serializable { private static final long serialVersionUID = 2072893447591548402L; public String name; public String url; public String iconUrl; public int priority; public ApkModel() { Random random = new Random(); priority = random.nextInt(100); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/GankModel.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; import java.util.Date; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/1 * 描 述: * 修订历史: * ================================================ */ public class GankModel implements Serializable { private static final long serialVersionUID = 6753210234564872868L; public String _id; public Date createdAt; public String desc; public List images; public Date publishedAt; public String source; public String type; public String url; public boolean used; public String who; } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/GankResponse.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/29 * 描 述: * 修订历史: * ================================================ */ public class GankResponse implements Serializable { private static final long serialVersionUID = -686453405647539973L; public boolean error; public T results; } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/ItemModel.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class ItemModel { public String title; public String des; public int type; public ItemModel() { } public ItemModel(String title, String des) { this.title = title; this.des = des; } public ItemModel(String title, String des, int type) { this.title = title; this.des = des; this.type = type; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/LzyResponse.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/28 * 描 述: * 修订历史: * ================================================ */ public class LzyResponse implements Serializable { private static final long serialVersionUID = 5213230387175987834L; public int code; public String msg; public T data; @Override public String toString() { return "LzyResponse{\n" +// "\tcode=" + code + "\n" +// "\tmsg='" + msg + "\'\n" +// "\tdata=" + data + "\n" +// '}'; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/ServerModel.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; /** * ================================================ * 作 者:jeasonlzy(廖子尧) * 版 本:1.0 * 创建日期:2016/4/7 * 描 述:我的Github地址 https://github.com/jeasonlzy * 修订历史: * ================================================ */ public class ServerModel implements Serializable { private static final long serialVersionUID = -828322761336296999L; public String method; public String ip; public String url; public String des; public String upload; public Author author; public class Author implements Serializable { private static final long serialVersionUID = 2701611773813762723L; public String name; public String fullname; public String github; public String address; public String qq; public String email; public String des; @Override public String toString() { return "Author{\n" +// "\tname='" + name + "\'\n" +// "\tfullname='" + fullname + "\'\n" +// "\tgithub='" + github + "\'\n" +// "\taddress='" + address + "\'\n" +// "\tqq='" + qq + "\'\n" +// "\temail='" + email + "\'\n" +// "\tdes='" + des + "\'\n" +// '}'; } } @Override public String toString() { return "ServerModel{\n" +// "\tmethod='" + method + "\'\n" +// "\tip='" + ip + "\'\n" +// "\turl='" + url + "\'\n" +// "\tdes='" + des + "\'\n" +// "\tupload='" + upload + "\'\n" +// "\tauthor=" + author + "\n" +// '}'; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/model/SimpleResponse.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.model; import java.io.Serializable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/28 * 描 述: * 修订历史: * ================================================ */ public class SimpleResponse implements Serializable { private static final long serialVersionUID = -1477609349345966116L; public int code; public String msg; public LzyResponse toLzyResponse() { LzyResponse lzyResponse = new LzyResponse(); lzyResponse.code = code; lzyResponse.msg = msg; return lzyResponse; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DesActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.text.format.Formatter; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.model.ApkModel; import com.lzy.demo.utils.ApkUtils; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Progress; import com.lzy.okgo.request.GetRequest; import com.lzy.okserver.OkDownload; import com.lzy.okserver.download.DownloadListener; import com.lzy.okserver.download.DownloadTask; import java.io.File; import java.text.NumberFormat; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class DesActivity extends BaseActivity { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.icon) ImageView icon; @Bind(R.id.name) TextView name; @Bind(R.id.downloadSize) TextView downloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView netSpeed; @Bind(R.id.pbProgress) ProgressBar pbProgress; @Bind(R.id.start) Button download; @Bind(R.id.remove) Button remove; @Bind(R.id.restart) Button restart; private NumberFormat numberFormat; private DownloadTask task; private ApkModel apk; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_details); initToolBar(toolbar, true, "下载管理"); apk = (ApkModel) getIntent().getSerializableExtra("apk"); numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); // 写法一:从内存中获取 if (OkDownload.getInstance().hasTask(apk.url)) { task = OkDownload.getInstance().getTask(apk.url)// .register(new DesListener("DesListener"))// .register(new LogDownloadListener()); } //写法二:从数据库中恢复 // Progress progress = DownloadManager.getInstance().get(apk.getUrl()); // if (progress != null) { // task = OkDownload.restore(progress)// // .register(new DesListener("DesListener"))// // .register(new LogDownloadListener()); // } displayImage(apk.iconUrl, icon); name.setText(apk.name); if (task != null) refreshUi(task.progress); } private void refreshUi(Progress progress) { String currentSize = Formatter.formatFileSize(this, progress.currentSize); String totalSize = Formatter.formatFileSize(this, progress.totalSize); downloadSize.setText(currentSize + "/" + totalSize); String speed = Formatter.formatFileSize(this, progress.speed); netSpeed.setText(String.format("%s/s", speed)); tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); switch (progress.status) { case Progress.NONE: download.setText("下载"); break; case Progress.LOADING: download.setText("暂停"); break; case Progress.PAUSE: download.setText("继续"); break; case Progress.WAITING: download.setText("等待"); break; case Progress.ERROR: download.setText("出错"); break; case Progress.FINISH: if (ApkUtils.isAvailable(this, new File(progress.filePath))) { download.setText("卸载"); } else { download.setText("安装"); } break; } } @Override protected void onDestroy() { super.onDestroy(); if (task != null) { task.unRegister("DesListener"); } } @OnClick(R.id.start) public void start() { if (task == null) { //这里只是演示,表示请求可以传参,怎么传都行,和okgo使用方法一样 GetRequest request = OkGo.get(apk.url)// .headers("aaa", "111")// .params("bbb", "222"); task = OkDownload.request(apk.url, request)// .priority(apk.priority)// .extra1(apk)// .save()// .register(new DesListener("DesListener"))// .register(new LogDownloadListener()); } switch (task.progress.status) { case Progress.PAUSE: case Progress.NONE: case Progress.ERROR: task.start(); break; case Progress.LOADING: task.pause(); break; case Progress.FINISH: File file = new File(task.progress.filePath); if (ApkUtils.isAvailable(this, file)) { ApkUtils.uninstall(this, ApkUtils.getPackageName(this, file.getAbsolutePath())); } else { ApkUtils.install(this, file); } break; } } @OnClick(R.id.remove) public void remove() { if (task != null) { task.remove(); task = null; } downloadSize.setText("--M/--M"); netSpeed.setText("---/s"); tvProgress.setText("--.--%"); pbProgress.setProgress(0); download.setText("下载"); } @OnClick(R.id.restart) public void restart() { if (task != null) task.restart(); } private class DesListener extends DownloadListener { DesListener(String tag) { super(tag); } @Override public void onStart(Progress progress) { } @Override public void onProgress(Progress progress) { refreshUi(progress); } @Override public void onFinish(File file, Progress progress) { } @Override public void onRemove(Progress progress) { } @Override public void onError(Progress progress) { Throwable throwable = progress.exception; if (throwable != null) throwable.printStackTrace(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DownloadAdapter.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.text.format.Formatter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.lzy.demo.R; import com.lzy.demo.model.ApkModel; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.ApkUtils; import com.lzy.okgo.db.DownloadManager; import com.lzy.okgo.model.Progress; import com.lzy.okserver.OkDownload; import com.lzy.okserver.download.DownloadListener; import com.lzy.okserver.download.DownloadTask; import java.io.File; import java.text.NumberFormat; import java.util.List; import java.util.Map; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/5 * 描 述: * 修订历史: * ================================================ */ public class DownloadAdapter extends RecyclerView.Adapter { public static final int TYPE_ALL = 0; public static final int TYPE_FINISH = 1; public static final int TYPE_ING = 2; private List values; private NumberFormat numberFormat; private LayoutInflater inflater; private Context context; private int type; public DownloadAdapter(Context context) { this.context = context; numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void updateData(int type) { //这里是将数据库的数据恢复 this.type = type; if (type == TYPE_ALL) values = OkDownload.restore(DownloadManager.getInstance().getAll()); if (type == TYPE_FINISH) values = OkDownload.restore(DownloadManager.getInstance().getFinished()); if (type == TYPE_ING) values = OkDownload.restore(DownloadManager.getInstance().getDownloading()); notifyDataSetChanged(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.item_download_manager, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { DownloadTask task = values.get(position); String tag = createTag(task); task.register(new ListDownloadListener(tag, holder))// .register(new LogDownloadListener()); holder.setTag(tag); holder.setTask(task); holder.bind(); holder.refresh(task.progress); } public void unRegister() { Map taskMap = OkDownload.getInstance().getTaskMap(); for (DownloadTask task : taskMap.values()) { task.unRegister(createTag(task)); } } private String createTag(DownloadTask task) { return type + "_" + task.progress.tag; } @Override public int getItemCount() { return values == null ? 0 : values.size(); } public class ViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.icon) ImageView icon; @Bind(R.id.name) TextView name; @Bind(R.id.priority) TextView priority; @Bind(R.id.downloadSize) TextView downloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView netSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; @Bind(R.id.start) Button download; private DownloadTask task; private String tag; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } public void setTask(DownloadTask task) { this.task = task; } public void bind() { Progress progress = task.progress; ApkModel apk = (ApkModel) progress.extra1; if (apk != null) { Glide.with(context).load(apk.iconUrl).error(R.mipmap.ic_launcher).into(icon); name.setText(apk.name); priority.setText(String.format("优先级:%s", progress.priority)); } else { name.setText(progress.fileName); } } public void refresh(Progress progress) { String currentSize = Formatter.formatFileSize(context, progress.currentSize); String totalSize = Formatter.formatFileSize(context, progress.totalSize); downloadSize.setText(currentSize + "/" + totalSize); priority.setText(String.format("优先级:%s", progress.priority)); switch (progress.status) { case Progress.NONE: netSpeed.setText("停止"); download.setText("下载"); break; case Progress.PAUSE: netSpeed.setText("暂停中"); download.setText("继续"); break; case Progress.ERROR: netSpeed.setText("下载出错"); download.setText("出错"); break; case Progress.WAITING: netSpeed.setText("等待中"); download.setText("等待"); break; case Progress.FINISH: netSpeed.setText("下载完成"); download.setText("完成"); break; case Progress.LOADING: String speed = Formatter.formatFileSize(context, progress.speed); netSpeed.setText(String.format("%s/s", speed)); download.setText("暂停"); break; } tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } @OnClick(R.id.start) public void start() { Progress progress = task.progress; switch (progress.status) { case Progress.PAUSE: case Progress.NONE: case Progress.ERROR: task.start(); break; case Progress.LOADING: task.pause(); break; case Progress.FINISH: if (ApkUtils.isAvailable(context, new File(progress.filePath))) { ApkUtils.uninstall(context, ApkUtils.getPackageName(context, progress.filePath)); } else { ApkUtils.install(context, new File(progress.filePath)); } break; } refresh(progress); } @OnClick(R.id.remove) public void remove() { task.remove(true); updateData(type); } @OnClick(R.id.restart) public void restart() { task.restart(); } public void setTag(String tag) { this.tag = tag; } public String getTag() { return tag; } } private class ListDownloadListener extends DownloadListener { private ViewHolder holder; ListDownloadListener(Object tag, ViewHolder holder) { super(tag); this.holder = holder; } @Override public void onStart(Progress progress) { } @Override public void onProgress(Progress progress) { if (tag == holder.getTag()) { holder.refresh(progress); } } @Override public void onError(Progress progress) { Throwable throwable = progress.exception; if (throwable != null) throwable.printStackTrace(); } @Override public void onFinish(File file, Progress progress) { Toast.makeText(context, "下载完成:" + progress.filePath, Toast.LENGTH_SHORT).show(); updateData(type); } @Override public void onRemove(Progress progress) { } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DownloadAllActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkDownload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class DownloadAllActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; private DownloadAdapter adapter; private OkDownload okDownload; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_all); initToolBar(toolbar, true, "所有任务"); okDownload = OkDownload.getInstance(); adapter = new DownloadAdapter(this); adapter.updateData(DownloadAdapter.TYPE_ALL); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okDownload.addOnAllTaskEndListener(this); } @Override public void onAllTaskEnd() { showToast("所有下载任务已结束"); } @Override protected void onDestroy() { super.onDestroy(); okDownload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override protected void onResume() { super.onResume(); adapter.notifyDataSetChanged(); } @OnClick(R.id.removeAll) public void removeAll(View view) { okDownload.removeAll(); adapter.updateData(DownloadAdapter.TYPE_ALL); adapter.notifyDataSetChanged(); } @OnClick(R.id.pauseAll) public void pauseAll(View view) { okDownload.pauseAll(); } @OnClick(R.id.startAll) public void startAll(View view) { okDownload.startAll(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DownloadFinishActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkDownload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class DownloadFinishActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { private DownloadAdapter adapter; private OkDownload okDownload; @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Bind(R.id.pauseAll) Button pauseAll; @Bind(R.id.startAll) Button startAll; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_all); initToolBar(toolbar, true, "已完成任务"); pauseAll.setVisibility(View.GONE); startAll.setVisibility(View.GONE); okDownload = OkDownload.getInstance(); adapter = new DownloadAdapter(this); adapter.updateData(DownloadAdapter.TYPE_FINISH); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okDownload.addOnAllTaskEndListener(this); } @Override public void onAllTaskEnd() { showToast("所有下载任务已结束"); } @Override protected void onDestroy() { super.onDestroy(); okDownload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override protected void onResume() { super.onResume(); adapter.notifyDataSetChanged(); } @OnClick(R.id.removeAll) public void removeAll(View view) { OkDownload.getInstance().removeAll(); adapter.updateData(DownloadAdapter.TYPE_FINISH); adapter.notifyDataSetChanged(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DownloadListActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.base.BaseRecyclerAdapter; import com.lzy.demo.base.DividerItemDecoration; import com.lzy.demo.model.ApkModel; import com.lzy.okgo.OkGo; import com.lzy.okgo.db.DownloadManager; import com.lzy.okgo.model.Progress; import com.lzy.okgo.request.GetRequest; import com.lzy.okserver.OkDownload; import java.io.File; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class DownloadListActivity extends BaseActivity { private static final int REQUEST_PERMISSION_STORAGE = 0x01; @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.targetFolder) TextView folder; @Bind(R.id.recyclerView) RecyclerView recyclerView; private List apks; private DownloadListAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_list); initToolBar(toolbar, true, "开始下载"); initData(); OkDownload.getInstance().setFolder(Environment.getExternalStorageDirectory().getAbsolutePath() + "/aaa/"); OkDownload.getInstance().getThreadPool().setCorePoolSize(3); folder.setText(String.format("下载路径: %s", OkDownload.getInstance().getFolder())); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL)); //从数据库中恢复数据 List progressList = DownloadManager.getInstance().getAll(); OkDownload.restore(progressList); adapter = new DownloadListAdapter(this); recyclerView.setAdapter(adapter); checkSDCardPermission(); } /** 检查SD卡权限 */ protected void checkSDCardPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_PERMISSION_STORAGE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //获取权限 } else { showToast("权限被禁止,无法下载文件!"); } } } @OnClick(R.id.startAll) public void startAll(View view) { for (ApkModel apk : apks) { //这里只是演示,表示请求可以传参,怎么传都行,和okgo使用方法一样 GetRequest request = OkGo.get(apk.url)// .headers("aaa", "111")// .params("bbb", "222"); //这里第一个参数是tag,代表下载任务的唯一标识,传任意字符串都行,需要保证唯一,我这里用url作为了tag OkDownload.request(apk.url, request)// .priority(apk.priority)// .extra1(apk)// .save()// .register(new LogDownloadListener())// .start(); adapter.notifyDataSetChanged(); } } @Override protected void onResume() { super.onResume(); adapter.notifyDataSetChanged(); } private class DownloadListAdapter extends BaseRecyclerAdapter { DownloadListAdapter(Context context) { super(context, apks); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.item_download_list, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { ApkModel apkModel = mDatas.get(position); holder.bind(apkModel); } } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { @Bind(R.id.name) TextView name; @Bind(R.id.priority) TextView priority; @Bind(R.id.icon) ImageView icon; @Bind(R.id.download) Button download; private ApkModel apk; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } public void bind(ApkModel apk) { this.apk = apk; if (OkDownload.getInstance().getTask(apk.url) != null) { download.setText("已在队列"); download.setEnabled(false); } else { download.setText("下载"); download.setEnabled(true); } priority.setText(String.format("优先级:%s", apk.priority)); name.setText(apk.name); displayImage(apk.iconUrl, icon); itemView.setOnClickListener(this); } @OnClick(R.id.download) public void download() { //这里只是演示,表示请求可以传参,怎么传都行,和okgo使用方法一样 GetRequest request = OkGo.get(apk.url)// .headers("aaa", "111")// .params("bbb", "222"); //这里第一个参数是tag,代表下载任务的唯一标识,传任意字符串都行,需要保证唯一,我这里用url作为了tag OkDownload.request(apk.url, request)// .priority(apk.priority)// .extra1(apk)// .save()// .register(new LogDownloadListener())// .start(); adapter.notifyDataSetChanged(); } @Override public void onClick(View v) { Intent intent = new Intent(getApplicationContext(), DesActivity.class); intent.putExtra("apk", apk); startActivity(intent); } } private void initData() { apks = new ArrayList<>(); ApkModel apk1 = new ApkModel(); apk1.name = "爱奇艺"; apk1.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0c10c4c0155c9adf1282af008ed329378d54112ac"; apk1.url = "http://121.29.10.1/f5.market.mi-img.com/download/AppStore/0b8b552a1df0a8bc417a5afae3a26b2fb1342a909/com.qiyi.video.apk"; apks.add(apk1); ApkModel apk2 = new ApkModel(); apk2.name = "微信"; apk2.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/00814b5dad9b54cc804466369c8cb18f23e23823f"; apk2.url = "http://116.117.158.129/f2.market.xiaomi.com/download/AppStore/04275951df2d94fee0a8210a3b51ae624cc34483a/com.tencent.mm.apk"; apks.add(apk2); ApkModel apk3 = new ApkModel(); apk3.name = "新浪微博"; apk3.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/01db44d7f809430661da4fff4d42e703007430f38"; apk3.url = "http://60.28.125.129/f1.market.xiaomi.com/download/AppStore/0ff41344f280f40c83a1bbf7f14279fb6542ebd2a/com.sina.weibo.apk"; apks.add(apk3); ApkModel apk4 = new ApkModel(); apk4.name = "QQ"; apk4.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/072725ca573700292b92e636ec126f51ba4429a50"; apk4.url = "http://121.29.10.1/f3.market.xiaomi.com/download/AppStore/0ff0604fd770f481927d1edfad35675a3568ba656/com.tencent.mobileqq.apk"; apks.add(apk4); ApkModel apk5 = new ApkModel(); apk5.name = "陌陌"; apk5.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/06006948e655c4dd11862d060bd055b4fd2b5c41b"; apk5.url = "http://121.18.239.1/f4.market.xiaomi.com/download/AppStore/096f34dec955dbde0597f4e701d1406000d432064/com.immomo.momo.apk"; apks.add(apk5); ApkModel apk6 = new ApkModel(); apk6.name = "手机淘宝"; apk6.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/017a859792d09d7394108e0a618411675ec43f220"; apk6.url = "http://121.29.10.1/f3.market.xiaomi.com/download/AppStore/0afc00452eb1a4dc42b20c9351eacacab4692a953/com.taobao.taobao.apk"; apks.add(apk6); ApkModel apk7 = new ApkModel(); apk7.name = "酷狗音乐"; apk7.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0f2f050e21e42f75c7ecca55d01ac4e5e4e40ca8d"; apk7.url = "http://121.18.239.1/f5.market.xiaomi.com/download/AppStore/053ed49c1545c6eec3e3e23b31568c731f940934f/com.kugou.android.apk"; apks.add(apk7); ApkModel apk8 = new ApkModel(); apk8.name = "网易云音乐"; apk8.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/02374548ac39f3b7cdbf5bea4b0535b5d1f432f23"; apk8.url = "http://121.18.239.1/f4.market.xiaomi.com/download/AppStore/0f458c5661acb492e30b808a2e3e4c8672e6b55e2/com.netease.cloudmusic.apk"; apks.add(apk8); ApkModel apk9 = new ApkModel(); apk9.name = "ofo共享单车"; apk9.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0fe1a5c6092f3d9fa5c4c1e3158e6ff33f6418152"; apk9.url = "http://60.28.125.1/f4.market.mi-img.com/download/AppStore/06954949fcd48414c16f726620cf2d52200550f56/so.ofo.labofo.apk"; apks.add(apk9); ApkModel apk10 = new ApkModel(); apk10.name = "摩拜单车"; apk10.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0863a058a811148a5174d9784b7be2f1114191f83"; apk10.url = "http://60.28.125.1/f4.market.xiaomi.com/download/AppStore/00cdeb4865c5a4a7d350fe30b9f812908a569cc8a/com.mobike.mobikeapp.apk"; apks.add(apk10); ApkModel apk11 = new ApkModel(); apk11.name = "贪吃蛇大作战"; apk11.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/09f7f5756d9d63bb149b7149b8bdde0769941f09b"; apk11.url = "http://60.22.46.1/f3.market.xiaomi.com/download/AppStore/0b02f24ffa8334bd21b16bd70ecacdb42374eb9cb/com.wepie.snake.new.mi.apk"; apks.add(apk11); ApkModel apk12 = new ApkModel(); apk12.name = "蘑菇街"; apk12.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0ab53044735e842c421a57954d86a77aea30cc1da"; apk12.url = "http://121.29.10.1/f5.market.xiaomi.com/download/AppStore/07a6ee4955e364c3f013b14055c37b8e4f6668161/com.mogujie.apk"; apks.add(apk12); ApkModel apk13 = new ApkModel(); apk13.name = "聚美优品"; apk13.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/080ed520b76d943e5533017a19bc76d9f554342d0"; apk13.url = "http://121.29.10.1/f5.market.mi-img.com/download/AppStore/0e70a572cd5fd6a3718941328238d78d71942aee0/com.jm.android.jumei.apk"; apks.add(apk13); ApkModel apk14 = new ApkModel(); apk14.name = "全民K歌"; apk14.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0f1f653261ff8b3a64324097224e40eface432b99"; apk14.url = "http://60.28.123.129/f4.market.xiaomi.com/download/AppStore/04f515e21146022934085454a1121e11ae34396ae/com.tencent.karaoke.apk"; apks.add(apk14); ApkModel apk15 = new ApkModel(); apk15.name = "书旗小说"; apk15.iconUrl = "http://file.market.xiaomi.com/thumbnail/PNG/l114/AppStore/0c9ce345aa2734b1202ddf32b6545d9407b18ba0b"; apk15.url = "http://60.28.125.129/f5.market.mi-img.com/download/AppStore/02d9c4035b248753314f46600cf7347a306426dc1/com.shuqi.controller.apk"; apks.add(apk15); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/DownloadingActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkDownload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class DownloadingActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { private DownloadAdapter adapter; private OkDownload okDownload; @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_all); initToolBar(toolbar, true, "下载中任务"); okDownload = OkDownload.getInstance(); adapter = new DownloadAdapter(this); adapter.updateData(DownloadAdapter.TYPE_ING); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okDownload.addOnAllTaskEndListener(this); } @Override public void onAllTaskEnd() { showToast("所有下载任务已结束"); } @Override protected void onDestroy() { super.onDestroy(); okDownload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override protected void onResume() { super.onResume(); adapter.notifyDataSetChanged(); } @OnClick(R.id.removeAll) public void removeAll(View view) { okDownload.removeAll(); adapter.updateData(DownloadAdapter.TYPE_ING); adapter.notifyDataSetChanged(); } @OnClick(R.id.pauseAll) public void pauseAll(View view) { okDownload.pauseAll(); } @OnClick(R.id.startAll) public void startAll(View view) { okDownload.startAll(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/LogDownloadListener.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import com.lzy.okgo.model.Progress; import com.lzy.okserver.download.DownloadListener; import java.io.File; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/7 * 描 述: * 修订历史: * ================================================ */ public class LogDownloadListener extends DownloadListener { public LogDownloadListener() { super("LogDownloadListener"); } @Override public void onStart(Progress progress) { System.out.println("onStart: " + progress); } @Override public void onProgress(Progress progress) { System.out.println("onProgress: " + progress); } @Override public void onError(Progress progress) { System.out.println("onError: " + progress); progress.exception.printStackTrace(); } @Override public void onFinish(File file, Progress progress) { System.out.println("onFinish: " + progress); } @Override public void onRemove(Progress progress) { System.out.println("onRemove: " + progress); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okdownload/OkDownloadFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okdownload; import android.content.Intent; import com.lzy.demo.base.MainFragment; import com.lzy.demo.model.ItemModel; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class OkDownloadFragment extends MainFragment { @Override public void fillData(List items) { items.add(new ItemModel("开始下载",// "1. 这个属于OkServer依赖中的功能,并不属于OkGo\n" +// "2. 支持断点下载和状态管理\n" +// "3. 支持自定义下载任务优先级\n" +// "4. 支持链试调用\n" +// "5. 最多支持扩展3个额外数据\n" +// "6. 支持同时指定多个下载目录")); items.add(new ItemModel("所有任务",// "1. 每个任务支持暂停,继续,重新下载,删除等操作\n" +// "2. 支持全部暂停,全部开始,全部删除\n" +// "3. 支持全局下载任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按下载中列表和下载完成列表筛选")); items.add(new ItemModel("下载中任务",// "1. 每个任务支持暂停,继续,重新下载,删除等操作\n" +// "2. 支持全部暂停,全部开始,全部删除\n" +// "3. 支持全局下载任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按下载中列表和下载完成列表筛选")); items.add(new ItemModel("已完成任务",// "1. 每个任务支持暂停,继续,重新下载,删除等操作\n" +// "2. 支持全部暂停,全部开始,全部删除\n" +// "3. 支持全局下载任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按下载中列表和下载完成列表筛选")); } @Override public void onItemClick(int position) { if (position == 0) startActivity(new Intent(context, DownloadListActivity.class)); if (position == 1) startActivity(new Intent(context, DownloadAllActivity.class)); if (position == 2) startActivity(new Intent(context, DownloadingActivity.class)); if (position == 3) startActivity(new Intent(context, DownloadFinishActivity.class)); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/BitmapRequestActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.BitmapDialogCallback; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class BitmapRequestActivity extends BaseDetailActivity { @Bind(R.id.imageView) ImageView imageView; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_bitmap_request); ButterKnife.bind(this); setTitle("请求图片"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.requestImage) public void requestJson(View view) { OkGo.get(Urls.URL_IMAGE)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new BitmapDialogCallback(this) { @Override public void onSuccess(Response response) { handleResponse(response); imageView.setImageBitmap(response.body()); } @Override public void onError(Response response) { handleError(response); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/CacheActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.app.Activity; import android.app.AlertDialog; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.DialogCallback; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.cache.CacheEntity; import com.lzy.okgo.cache.CacheMode; import com.lzy.okgo.db.CacheManager; import com.lzy.okgo.model.Response; import java.util.List; import butterknife.ButterKnife; import butterknife.OnClick; import okhttp3.Call; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class CacheActivity extends BaseDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_cache); ButterKnife.bind(this); setTitle("网络缓存基本用法"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @SuppressWarnings("unchecked") @OnClick(R.id.getAll) public void getAll(View view) { // 获取所有的缓存,但是一般每个缓存的泛型都不一样,所以缓存的泛型使用 ? List> all = CacheManager.getInstance().getAll(); StringBuilder sb = new StringBuilder(); sb.append("共" + all.size() + "条缓存:").append("\n\n"); for (int i = 0; i < all.size(); i++) { CacheEntity cacheEntity = all.get(i); sb.append("第" + (i + 1) + "条缓存:").append("\n").append(cacheEntity).append("\n\n"); } AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("所有缓存显示").setMessage(sb.toString()).show(); } @OnClick(R.id.clear) public void clear(View view) { boolean clear = CacheManager.getInstance().clear(); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("清除缓存").setMessage("是否清除成功:" + clear).show(); } @OnClick(R.id.no_cache) public void no_cache(View view) { OkGo.>get(Urls.URL_CACHE)// .tag(this)// .cacheMode(CacheMode.NO_CACHE)// .cacheKey("no_cache") //对于无缓存模式,该参数无效 .cacheTime(5000) //对于无缓存模式,该时间无效 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new CacheCallBack(this)); } @OnClick(R.id.cache_default) public void cache_default(View view) { OkGo.>get(Urls.URL_CACHE)// .tag(this)// .cacheMode(CacheMode.DEFAULT)// .cacheKey("cache_default")// .cacheTime(5000)//对于默认的缓存模式,该时间无效,依靠的是服务端对304缓存的控制 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new CacheCallBack(this)); } @OnClick(R.id.request_failed_read_cache) public void request_failed_read_cache(View view) { OkGo.>get(Urls.URL_CACHE)// .tag(this)// .cacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)// .cacheKey("request_failed_read_cache")// .cacheTime(5000) // 单位毫秒.5秒后过期 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new CacheCallBack(this)); } @OnClick(R.id.if_none_cache_request) public void if_none_cache_request(View view) { OkGo.>get(Urls.URL_CACHE)// .tag(this)// .cacheMode(CacheMode.IF_NONE_CACHE_REQUEST)// .cacheKey("if_none_cache_request")// .cacheTime(5000) // 单位毫秒.5秒后过期 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new CacheCallBack(this)); } @OnClick(R.id.first_cache_then_request) public void first_cache_then_request(View view) { OkGo.>get(Urls.URL_CACHE)// .tag(this)// .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST)// .cacheKey("first_cache_then_request")// .cacheTime(5000) // 单位毫秒.5秒后过期 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new CacheCallBack(this)); } private class CacheCallBack extends DialogCallback> { CacheCallBack(Activity activity) { super(activity); } @Override public void onSuccess(Response> response) { handleResponse(response); Call call = response.getRawCall(); requestState.setText("请求成功 是否来自缓存:false 请求方式:" + call.request().method() + "\n" + "url:" + call.request().url()); } @Override public void onCacheSuccess(Response> response) { handleResponse(response); Call call = response.getRawCall(); requestState.setText("请求成功 是否来自缓存:true 请求方式:" + call.request().method() + "\n" + "url:" + call.request().url()); } @Override public void onError(Response> response) { handleError(response); Call call = response.getRawCall(); requestState.setText("请求失败 是否来自缓存:false 请求方式:" + call.request().method() + "\n" + "url:" + call.request().url()); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/CommonActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.base.DividerItemDecoration; import com.lzy.demo.model.ItemModel; import java.util.ArrayList; import java.util.List; import butterknife.Bind; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class CommonActivity extends BaseActivity { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; private List data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler); initToolBar(toolbar, true, "OkGo功能介绍"); initData(); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL)); recyclerView.setAdapter(new MainAdapter(data)); } private void initData() { data = new ArrayList<>(); data.add(new ItemModel("请求方法演示", "目前支持 GET,HEAD,OPTIONS,POST,PUT,DELETE, PATCH, TRACE")); data.add(new ItemModel("请求图片", "请求服务器返回bitmap对象")); data.add(new ItemModel("普通上传数据", "可以向服务器上传任意类型的文本数据,包括 String,JSONObject,JSONArray,byte[],文件等")); data.add(new ItemModel("网络缓存基本用法", "默认提供了四种缓存模式,根据需要选择使用")); data.add(new ItemModel("支持https请求", "支持 cer,bks 证书,支持双向认证")); data.add(new ItemModel("cookie管理与session保持", "支持cookie的自动管理,也支持自己手动管理cookie,自动session保持")); data.add(new ItemModel("同步请求", "允许直接返回Response对象,会阻塞主线程,需要自行开启子线程")); data.add(new ItemModel("301重定向", "支持301重定向请求")); data.add(new ItemModel("测试页面", "用于测试特殊情况下的网络连接,可忽略")); } private class MainAdapter extends BaseQuickAdapter { MainAdapter(List data) { super(R.layout.item_main_list, data); } @Override protected void convert(final BaseViewHolder baseViewHolder, ItemModel itemModel) { baseViewHolder.setText(R.id.title, itemModel.title); baseViewHolder.setText(R.id.des, itemModel.des); baseViewHolder.getConvertView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = baseViewHolder.getAdapterPosition(); if (position == 0) startActivity(new Intent(CommonActivity.this, MethodActivity.class)); if (position == 1) startActivity(new Intent(CommonActivity.this, BitmapRequestActivity.class)); if (position == 2) startActivity(new Intent(CommonActivity.this, UpActivity.class)); if (position == 3) startActivity(new Intent(CommonActivity.this, CacheActivity.class)); if (position == 4) startActivity(new Intent(CommonActivity.this, HttpsActivity.class)); if (position == 5) startActivity(new Intent(CommonActivity.this, CookieActivity.class)); if (position == 6) startActivity(new Intent(CommonActivity.this, SyncActivity.class)); if (position == 7) startActivity(new Intent(CommonActivity.this, RedirectActivity.class)); if (position == 8) startActivity(new Intent(CommonActivity.this, TestActivity.class)); } }); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/CookieActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.StringDialogCallback; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.cookie.store.CookieStore; import com.lzy.okgo.model.Response; import java.util.List; import butterknife.ButterKnife; import butterknife.OnClick; import okhttp3.Cookie; import okhttp3.HttpUrl; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class CookieActivity extends BaseDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_cookie); ButterKnife.bind(this); setTitle("cookie管理与session保持"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.getCookie) public void getCookie(View view) { //一般手动取出cookie的目的只是交给 webview 等等,非必要情况不要自己操作 CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore(); HttpUrl httpUrl = HttpUrl.parse(Urls.URL_METHOD); List cookies = cookieStore.getCookie(httpUrl); showToast(httpUrl.host() + "对应的cookie如下:" + cookies.toString()); } @OnClick(R.id.getAllCookie) public void getAllCookie(View view) { //一般手动取出cookie的目的只是交给 webview 等等,非必要情况不要自己操作 CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore(); List allCookie = cookieStore.getAllCookie(); showToast("所有cookie如下:" + allCookie.toString()); } @OnClick(R.id.addCookie) public void addCookie(View view) { HttpUrl httpUrl = HttpUrl.parse(Urls.URL_METHOD); Cookie.Builder builder = new Cookie.Builder(); Cookie cookie = builder.name("myCookieKey1").value("myCookieValue1").domain(httpUrl.host()).build(); CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore(); cookieStore.saveCookie(httpUrl, cookie); showToast("详细添加cookie的代码,请看demo的代码"); OkGo.post(Urls.URL_TEXT_UPLOAD)// .tag(this)// .execute(new StringDialogCallback(this) { @Override public void onSuccess(Response response) { handleResponse(response); } @Override public void onError(Response response) { handleError(response); } }); } @OnClick(R.id.removeCookie) public void removeCookie(View view) { HttpUrl httpUrl = HttpUrl.parse(Urls.URL_METHOD); CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore(); cookieStore.removeCookie(httpUrl); showToast("详细移除cookie的代码,请看demo的代码"); } @OnClick(R.id.updateCookie) public void updateCookie(View view) { showToast("暂时未实现,可以先移除再添加,效果一样"); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/FormUploadActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.content.Intent; import android.os.Bundle; import android.text.format.Formatter; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.JsonCallback; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.GlideImageLoader; import com.lzy.demo.utils.Urls; import com.lzy.imagepicker.ImagePicker; import com.lzy.imagepicker.bean.ImageItem; import com.lzy.imagepicker.ui.ImageGridActivity; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Progress; import com.lzy.okgo.model.Response; import com.lzy.okgo.request.base.Request; import java.io.File; import java.text.NumberFormat; import java.util.ArrayList; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class FormUploadActivity extends BaseDetailActivity { @Bind(R.id.formUpload) Button btnFormUpload; @Bind(R.id.downloadSize) TextView tvDownloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView tvNetSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; @Bind(R.id.images) TextView tvImages; private ArrayList imageItems; private NumberFormat numberFormat; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_form_upload); ButterKnife.bind(this); setTitle("文件上传"); numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.selectImage) public void selectImage(View view) { ImagePicker imagePicker = ImagePicker.getInstance(); imagePicker.setImageLoader(new GlideImageLoader()); imagePicker.setMultiMode(true); //多选 imagePicker.setShowCamera(true); //显示拍照按钮 imagePicker.setSelectLimit(9); //最多选择9张 imagePicker.setCrop(false); //不进行裁剪 Intent intent = new Intent(this, ImageGridActivity.class); startActivityForResult(intent, 100); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == ImagePicker.RESULT_CODE_ITEMS) { if (data != null && requestCode == 100) { imageItems = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS); if (imageItems != null && imageItems.size() > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < imageItems.size(); i++) { if (i == imageItems.size() - 1) sb.append("图片").append(i + 1).append(" : ").append(imageItems.get(i).path); else sb.append("图片").append(i + 1).append(" : ").append(imageItems.get(i).path).append("\n"); } tvImages.setText(sb.toString()); } else { tvImages.setText("--"); } } else { Toast.makeText(this, "没有选择图片", Toast.LENGTH_SHORT).show(); tvImages.setText("--"); } } } @OnClick(R.id.formUpload) public void formUpload(View view) { ArrayList files = new ArrayList<>(); if (imageItems != null && imageItems.size() > 0) { for (int i = 0; i < imageItems.size(); i++) { files.add(new File(imageItems.get(i).path)); } } //拼接参数 OkGo.>post(Urls.URL_FORM_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// .headers("header2", "headerValue2")// .params("param1", "paramValue1")// .params("param2", "paramValue2")// // .params("file1",new File("文件路径")) //这种方式为一个key,对应一个文件 // .params("file2",new File("文件路径")) // .params("file3",new File("文件路径")) .addFileParams("file", files) // 这种方式为同一个key,上传多个文件 .execute(new JsonCallback>() { @Override public void onStart(Request, ? extends Request> request) { btnFormUpload.setText("正在上传中..."); } @Override public void onSuccess(Response> response) { handleResponse(response); btnFormUpload.setText("上传完成"); } @Override public void onError(Response> response) { handleError(response); btnFormUpload.setText("上传出错"); } @Override public void uploadProgress(Progress progress) { System.out.println("uploadProgress: " + progress); String downloadLength = Formatter.formatFileSize(getApplicationContext(), progress.currentSize); String totalLength = Formatter.formatFileSize(getApplicationContext(), progress.totalSize); tvDownloadSize.setText(downloadLength + "/" + totalLength); String speed = Formatter.formatFileSize(getApplicationContext(), progress.speed); tvNetSpeed.setText(String.format("%s/s", speed)); tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/HttpsActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.StringDialogCallback; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class HttpsActivity extends BaseDetailActivity { private static final String CER_12306 = "-----BEGIN CERTIFICATE-----\n" + // "MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn\n" + // "BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X\n" + // "DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp\n" + // "bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3\n" + // "DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2\n" + // "9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6\n" + // "D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle\n" + // "tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov\n" + // "LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt\n" + // "x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV\n" + // "23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ\n" + // "og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==\n" + // "-----END CERTIFICATE-----"; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_https); ButterKnife.bind(this); setTitle("支持https请求"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.btn_none_https_request) public void btn_none_https_request(View view) { //CA 认证的证书不需要任何设置,和http请求一样 OkGo.get("https://github.com/jeasonlzy")// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new StringDialogCallback(this) { @Override public void onError(Response response) { handleError(response); } @Override public void onSuccess(Response response) { handleResponse(response); } }); } @OnClick(R.id.btn_https_request) public void btn_https_request(View view) { //自签名的证书需要在全局初始化的时候设置,详细看初始化的代码 OkGo.get("https://kyfw.12306.cn/otn")// .tag(this)// .headers("Connection", "close") //如果对于部分自签名的https访问不成功,需要加上该控制头 .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new StringDialogCallback(this) { @Override public void onError(Response response) { handleError(response); } @Override public void onSuccess(Response response) { handleResponse(response); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/JsonActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.DialogCallback; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import java.util.List; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class JsonActivity extends BaseDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_custom_request); ButterKnife.bind(this); actionBar.setTitle("自动解析JSON对象"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } /** * 解析javabean对象 */ @OnClick(R.id.requestJson) public void requestJson(View view) { OkGo.>get(Urls.URL_JSONOBJECT)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); } /** * 解析集合对象 */ @OnClick(R.id.requestJsonArray) public void requestJsonArray(View view) { OkGo.>>get(Urls.URL_JSONARRAY)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>>(this) { @Override public void onSuccess(Response>> response) { handleResponse(response); } @Override public void onError(Response>> response) { handleError(response); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/MethodActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.graphics.Color; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.DialogCallback; import com.lzy.demo.callback.StringDialogCallback; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.ColorUtils; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import butterknife.Bind; import butterknife.ButterKnife; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class MethodActivity extends BaseDetailActivity implements AdapterView.OnItemClickListener { @Bind(R.id.gridView) GridView gridView; private String[] methods = {"GET", "HEAD", "OPTIONS", "POST", "PUT", "DELETE", "PATCH", "TRACE"}; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_method); ButterKnife.bind(this); setTitle("请求方法演示"); gridView.setAdapter(new MyAdapter()); gridView.setOnItemClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { switch (position) { case 0: OkGo.>get(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 1: OkGo.head(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new StringDialogCallback(this) { @Override public void onSuccess(Response response) { handleResponse(response); } @Override public void onError(Response response) { handleError(response); } }); break; case 2: OkGo.>options(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 3: OkGo.>post(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .params("param2", "paramValue2")// .params("param3", "paramValue3")// .isMultipart(true) //强制使用 multipart/form-data 表单上传(只是演示,不需要的话不要设置。默认就是false) .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 4: OkGo.>put(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 5: OkGo.>delete(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .upString("这是要上传的数据")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 6: OkGo.>patch(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .upString("这是要上传的数据")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; case 7: OkGo.>trace(Urls.URL_METHOD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); break; } } private class MyAdapter extends BaseAdapter { @Override public int getCount() { return methods.length; } @Override public String getItem(int position) { return methods[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = new TextView(getApplicationContext()); } TextView textView = (TextView) convertView; textView.setGravity(Gravity.CENTER); textView.setHeight(200); textView.setText(getItem(position)); textView.setTextColor(Color.WHITE); textView.setTextSize(16); textView.setBackgroundColor(ColorUtils.randomColor()); return textView; } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/OkGoFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.content.Intent; import com.lzy.demo.base.MainFragment; import com.lzy.demo.model.ItemModel; import com.lzy.demo.supercache.SuperCacheActivity; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class OkGoFragment extends MainFragment { @Override public void fillData(List items) { items.add(new ItemModel("强大的缓存示例 -- 先联网获取数据,然后断开网络再进试试",// "1.OkGo的强大的缓存功能,让你代码无需关心数据来源,专注于业务逻辑的实现\n" +// "2.内置五种缓存模式满足你各种使用场景\n" +// "3.支持自定义缓存策略,可以按照自己的需求改写缓存逻辑\n" +// "4.支持自定义缓存过期时间")); items.add(new ItemModel("基本功能",// "1.GET,HEAD,OPTIONS,POST,PUT,DELETE, PATCH, TRACE 请求方法演示\n" +// "2.请求服务器返回bitmap对象\n" +// "3.支持https请求\n" +// "4.支持同步请求\n" +// "5.支持301重定向")); items.add(new ItemModel("自动解析JSON对象",// "1.自动解析JSONObject对象\n" + // "2.自动解析JSONArray对象")); items.add(new ItemModel("文件下载",// "1.支持大文件或小文件下载,无论多大文件都不会发生OOM\n" +// "2.支持监听下载进度和下载网速\n" +// "3.支持自定义下载目录和下载文件名")); items.add(new ItemModel("文件上传",// "1.支持上传单个文件\n" +// "2.支持同时上传多个文件\n" +// "3.支持多个文件多个参数同时上传\n" +// "4.支持大文件上传,无论多大都不会发生OOM\n" +// "5.支持监听上传进度和上传网速")); } @Override public void onItemClick(int position) { if (position == 0) startActivity(new Intent(context, SuperCacheActivity.class)); if (position == 1) startActivity(new Intent(context, CommonActivity.class)); if (position == 2) startActivity(new Intent(context, JsonActivity.class)); if (position == 3) startActivity(new Intent(context, SimpleDownloadActivity.class)); if (position == 4) startActivity(new Intent(context, FormUploadActivity.class)); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/RedirectActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.StringDialogCallback; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RedirectActivity extends BaseDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_redirect); ButterKnife.bind(this); setTitle("301重定向"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.redirect) public void redirect(View view) { OkGo.get(Urls.URL_REDIRECT)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new StringDialogCallback(this) { @Override public void onSuccess(Response response) { handleResponse(response); responseData.setText("注意看请求头的url和响应头的url是不一样的!\n这代表了在请求过程中发生了重定向," +// "okhttp默认将重定向封装在了请求内部,只有最后一次请求的数据会被真正的请求下来触发回调,中间过程" +// "是默认实现的,不会触发回调!"); } @Override public void onError(Response response) { handleError(response); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/SimpleDownloadActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.text.format.Formatter; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.FileCallback; import com.lzy.okgo.model.Progress; import com.lzy.okgo.model.Response; import com.lzy.okgo.request.base.Request; import java.io.File; import java.text.NumberFormat; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class SimpleDownloadActivity extends BaseDetailActivity { private static final int REQUEST_PERMISSION_STORAGE = 0x01; @Bind(R.id.fileDownload) Button btnFileDownload; @Bind(R.id.downloadSize) TextView tvDownloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView tvNetSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; private NumberFormat numberFormat; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_file_download); ButterKnife.bind(this); setTitle("简单文件下载"); numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); checkSDCardPermission(); } /** 检查SD卡权限 */ protected void checkSDCardPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_PERMISSION_STORAGE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //获取权限 } else { showToast("权限被禁止,无法下载文件!"); } } } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.fileDownload) public void fileDownload(View view) { OkGo.get(Urls.URL_DOWNLOAD)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .execute(new FileCallback("OkGo.apk") { @Override public void onStart(Request request) { btnFileDownload.setText("正在下载中"); } @Override public void onSuccess(Response response) { handleResponse(response); btnFileDownload.setText("下载完成"); } @Override public void onError(Response response) { handleError(response); btnFileDownload.setText("下载出错"); } @Override public void downloadProgress(Progress progress) { System.out.println(progress); String downloadLength = Formatter.formatFileSize(getApplicationContext(), progress.currentSize); String totalLength = Formatter.formatFileSize(getApplicationContext(), progress.totalSize); tvDownloadSize.setText(downloadLength + "/" + totalLength); String speed = Formatter.formatFileSize(getApplicationContext(), progress.speed); tvNetSpeed.setText(String.format("%s/s", speed)); tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/SyncActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Toast; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.adapter.Call; import com.lzy.okgo.convert.StringConvert; import com.lzy.okgo.model.Response; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class SyncActivity extends BaseDetailActivity { private Handler handler = new InnerHandler(); private class InnerHandler extends Handler { @Override public void handleMessage(Message msg) { String data = (String) msg.obj; System.out.println("同步请求的数据:" + data); Toast.makeText(getApplicationContext(), "同步请求成功" + data, Toast.LENGTH_SHORT).show(); } } @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_sync); ButterKnife.bind(this); setTitle("同步请求"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.sync) public void sync(View view) { new Thread(new Runnable() { @Override public void run() { try { // //同步会阻塞主线程,必须开线程 // Response response = OkGo.get(Urls.URL_JSONOBJECT)// // .tag(this)// // .headers("header1", "headerValue1")// // .params("param1", "paramValue1")// // .execute(); //不传callback即为同步请求 Call call = OkGo.get(Urls.URL_JSONOBJECT)// .tag(this)// .headers("header1", "headerValue1")// .params("param1", "paramValue1")// .converter(new StringConvert())// .adapt(); Response response = call.execute(); Message message = Message.obtain(); message.obj = response.body(); handler.sendMessage(message); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/TestActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.callback.JsonCallback; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.adapter.Call; import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.model.HttpHeaders; import com.lzy.okgo.model.Response; import org.json.JSONObject; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class TestActivity extends BaseActivity { @Bind(R.id.image) ImageView imageView; @Bind(R.id.edit) EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); setTitle("测试页面"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.btn1) public void btn1(View view) { OkGo.get(Urls.URL_JSONOBJECT)// .execute(new JsonCallback() { @Override public void onSuccess(Response response) { System.out.println(response.body()); } @Override public void onError(Response response) { response.getException().printStackTrace(); } }); } @OnClick(R.id.btn2) public void btn2(View view) { new Thread(new Runnable() { @Override public void run() { try { Call adapt = OkGo.get(Urls.URL_JSONOBJECT).adapt(); Response response = adapt.execute(); System.out.println("body " + response.body()); Throwable exception = response.getException(); if (exception != null) exception.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } @OnClick(R.id.btn3) public void btn3(View view) { OkGo.get("asdfasf")// .tag(this)// .headers(HttpHeaders.HEAD_KEY_USER_AGENT, "abcd")// .execute(new StringCallback() { @Override public void onSuccess(Response response) { } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okgo/UpActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okgo; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.lzy.demo.R; import com.lzy.demo.base.BaseDetailActivity; import com.lzy.demo.callback.DialogCallback; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.GlideImageLoader; import com.lzy.demo.utils.Urls; import com.lzy.imagepicker.ImagePicker; import com.lzy.imagepicker.bean.ImageItem; import com.lzy.imagepicker.ui.ImageGridActivity; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import org.json.JSONObject; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class UpActivity extends BaseDetailActivity { @Bind(R.id.images) TextView tvImages; private ImageItem imageItem; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_up_text); ButterKnife.bind(this); setTitle("普通上传数据"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 OkGo.getInstance().cancelTag(this); } @OnClick(R.id.selectImage) public void selectImage(View view) { ImagePicker imagePicker = ImagePicker.getInstance(); imagePicker.setImageLoader(new GlideImageLoader()); imagePicker.setMultiMode(false); //单选 imagePicker.setShowCamera(true); //显示拍照按钮 imagePicker.setSelectLimit(9); //最多选择9张 imagePicker.setCrop(false); //不进行裁剪 Intent intent = new Intent(this, ImageGridActivity.class); startActivityForResult(intent, 100); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == ImagePicker.RESULT_CODE_ITEMS) { if (data != null && requestCode == 100) { //noinspection unchecked List imageItems = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS); if (imageItems != null && imageItems.size() > 0) { imageItem = imageItems.get(0); tvImages.setText(imageItem.path); } else { tvImages.setText("--"); } } else { Toast.makeText(this, "没有选择图片", Toast.LENGTH_SHORT).show(); tvImages.setText("--"); } } } @OnClick(R.id.upJson) public void upJson(View view) { HashMap params = new HashMap<>(); params.put("key1", "value1"); params.put("key2", "这里是需要提交的json格式数据"); params.put("key3", "也可以使用三方工具将对象转成json字符串"); params.put("key4", "其实你怎么高兴怎么写都行"); JSONObject jsonObject = new JSONObject(params); OkGo.>post(Urls.URL_TEXT_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// // .params("param1", "paramValue1")// 这里不要使用params,upJson 与 params 是互斥的,只有 upJson 的数据会被上传 .upJson(jsonObject)// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); } @OnClick(R.id.upString) public void upString(View view) { OkGo.>post(Urls.URL_TEXT_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// // .params("param1", "paramValue1")// 这里不要使用params,upString 与 params 是互斥的,只有 upString 的数据会被上传 .upString("这是要上传的长文本数据!")// // .upString("这是要上传的长文本数据!", MediaType.parse("application/xml"))// 比如上传xml数据,这里就可以自己指定请求头 .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); } @OnClick(R.id.upBytes) public void upBytes(View view) { OkGo.>post(Urls.URL_TEXT_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// // .params("param1", "paramValue1")// 这里不要使用params,upBytes 与 params 是互斥的,只有 upBytes 的数据会被上传 .upBytes("这是字节数据".getBytes())// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); } @OnClick(R.id.upFile) public void upFile(View view) { if (imageItem == null) { showToast("请先选择文件!"); return; } OkGo.>post(Urls.URL_TEXT_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// // .params("param1", "paramValue1")// 这里不要使用params,upBytes 与 params 是互斥的,只有 upBytes 的数据会被上传 .upFile(new File(imageItem.path))// .execute(new DialogCallback>(this) { @Override public void onSuccess(Response> response) { handleResponse(response); } @Override public void onError(Response> response) { handleError(response); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/OkRx2Fragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.content.Intent; import com.lzy.demo.base.MainFragment; import com.lzy.demo.model.ItemModel; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class OkRx2Fragment extends MainFragment { @Override public void fillData(List items) { items.add(new ItemModel("基本请求", // "1.支持GET,HEAD,OPTIONS,POST,PUT,DELETE, PATCH, TRACE 8种请求方式\n" +// "2.自动解析JSONObject对象\n" +// "3.自动解析JSONArray对象\n" +// "4.上传string文本\n" +// "5.上传json数据")); items.add(new ItemModel("rx使用缓存", "okrx的缓存与okgo的缓存一模一样,详细看okrx的文档介绍")); items.add(new ItemModel("统一管理请求", "如果你熟悉Retrofit,那么和Retrofit一样,可以使用一个Api类管理所有的请求")); items.add(new ItemModel("请求图片", "请求服务器返回bitmap对象")); items.add(new ItemModel("文件上传", "支持参数和文件一起上传,并回调上传进度")); items.add(new ItemModel("文件下载", "支持下载进度回调")); } @Override public void onItemClick(int position) { if (position == 0) startActivity(new Intent(context, RxCommonActivity.class)); if (position == 1) startActivity(new Intent(context, RxCacheActivity.class)); if (position == 2) startActivity(new Intent(context, RxRetrofitActivity.class)); if (position == 3) startActivity(new Intent(context, RxBitmapActivity.class)); if (position == 4) startActivity(new Intent(context, RxFormUploadActivity.class)); if (position == 5) startActivity(new Intent(context, RxFileDownloadActivity.class)); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/OkRxFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import com.lzy.demo.base.MainFragment; import com.lzy.demo.model.ItemModel; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class OkRxFragment extends MainFragment { @Override public void fillData(List items) { items.add(new ItemModel("OkRx是OkGo结合RxJava的扩展项目\n" +// "OkRx2是OkGo结合RxJava2的扩展项目\n" +// "他们的使用方法完全一样,在此不做演示,详细请看OkRx2的使用介绍", // "1.完美结合RxJava\n" +// "2.比Retrofit更简单方便\n" +// "3.网络请求和RxJava调用,一条链点到底\n" +// "4.支持JSON数据的自动解析转换")); } @Override public void onItemClick(int position) { } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxBitmapActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.okgo.model.Response; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxBitmapActivity extends BaseRxDetailActivity { @Bind(R.id.imageView) ImageView imageView; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_bitmap_request); ButterKnife.bind(this); setTitle("请求图片"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.requestImage) public void requestImage(View view) { ServerApi.getBitmap("aaa", "bbb")// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { handleResponse(response); imageView.setImageBitmap(response.body()); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 handleError(null); showToast("请求失败"); } @Override public void onComplete() { dismissLoading(); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxCacheActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.cache.CacheMode; import com.lzy.okgo.convert.StringConvert; import com.lzy.okgo.model.Response; import com.lzy.okrx2.adapter.ObservableResponse; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxCacheActivity extends BaseRxDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_rx_cache); ButterKnife.bind(this); setTitle("使用缓存"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.cache) public void cache(View view) { // 详细看文档: https://github.com/jeasonlzy/okhttp-OkGo/wiki/OkRx OkGo.post(Urls.URL_METHOD)// .headers("aaa", "111")// .params("bbb", "222")// .cacheKey("rx_cache") //这里完全同okgo的配置一样 .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST) //这里完全同okgo的配置一样 .converter(new StringConvert())// .adapt(new ObservableResponse())// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxCommonActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.os.Bundle; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.demo.callback.JsonConvert; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.convert.StringConvert; import com.lzy.okgo.model.Response; import com.lzy.okrx2.adapter.ObservableBody; import com.lzy.okrx2.adapter.ObservableResponse; import org.json.JSONObject; import java.util.HashMap; import java.util.List; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxCommonActivity extends BaseRxDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_rx_common); ButterKnife.bind(this); setTitle("OkRx基本请求"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.commonRequest) public void commonRequest(View view) { OkGo.post(Urls.URL_METHOD)// .headers("aaa", "111")// .params("bbb", "222")// .converter(new StringConvert())// .adapt(new ObservableResponse())// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.jsonRequest) public void jsonRequest(View view) { OkGo.>get(Urls.URL_JSONOBJECT)// .headers("aaa", "111")// .params("bbb", "222")// .converter(new JsonConvert>() {})// .adapt(new ObservableBody>())// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .map(new Function, ServerModel>() { @Override public ServerModel apply(@NonNull LzyResponse response) throws Exception { return response.data; } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull ServerModel serverModel) { handleResponse(serverModel); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.jsonArrayRequest) public void jsonArrayRequest(View view) { OkGo.>>get(Urls.URL_JSONARRAY)// .headers("aaa", "111")// .params("bbb", "222")// .converter(new JsonConvert>>() {})// .adapt(new ObservableBody>>())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .map(new Function>, List>() { @Override public List apply(@NonNull LzyResponse> response) throws Exception { return response.data; } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull List response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.upString) public void upString(View view) { OkGo.post(Urls.URL_TEXT_UPLOAD)// .headers("aaa", "111")// .upString("上传的文本。。。")// .converter(new StringConvert())// .adapt(new ObservableResponse())// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.upJson) public void upJson(View view) { HashMap params = new HashMap<>(); params.put("key1", "value1"); params.put("key2", "这里是需要提交的json格式数据"); params.put("key3", "也可以使用三方工具将对象转成json字符串"); params.put("key4", "其实你怎么高兴怎么写都行"); JSONObject jsonObject = new JSONObject(params); OkGo.post(Urls.URL_TEXT_UPLOAD)// .headers("aaa", "111")// .upJson(jsonObject)// .converter(new StringConvert())// .adapt(new ObservableResponse())// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxFileDownloadActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.text.TextUtils; import android.text.format.Formatter; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.FileCallback; import com.lzy.okgo.convert.FileConvert; import com.lzy.okgo.model.Progress; import com.lzy.okgo.model.Response; import com.lzy.okrx2.adapter.ObservableResponse; import java.io.File; import java.text.NumberFormat; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxFileDownloadActivity extends BaseRxDetailActivity { private static final int REQUEST_PERMISSION_STORAGE = 0x01; @Bind(R.id.et_url) EditText etUrl; @Bind(R.id.fileDownload1) Button btnFileDownload1; @Bind(R.id.fileDownload2) Button btnFileDownload2; @Bind(R.id.downloadSize) TextView tvDownloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView tvNetSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; private NumberFormat numberFormat; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_rx_file_download); ButterKnife.bind(this); setTitle("文件下载"); numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); checkSDCardPermission(); } /** 检查SD卡权限 */ protected void checkSDCardPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @android.support.annotation.NonNull String[] permissions, @android.support.annotation.NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_PERMISSION_STORAGE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //获取权限 } else { showToast("权限被禁止,无法下载文件!"); } } } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.fileDownload1) public void fileDownload1(View view) { //使用okrx直接下,下载进度封装比较麻烦,推荐使用回调方式 String etString = etUrl.getText().toString(); String url = TextUtils.isEmpty(etString) ? Urls.URL_DOWNLOAD : etString; OkGo.get(url)// .headers("aaa", "111")// .params("bbb", "222")// .converter(new FileConvert())// .adapt(new ObservableResponse()).subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { btnFileDownload1.setText("正在下载中...\n使用Rx方式做进度监听稍显麻烦,推荐使用方式2"); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { btnFileDownload1.setText("下载完成"); handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); btnFileDownload1.setText("下载出错"); showToast(e.getMessage()); handleError(null); } @Override public void onComplete() { } }); } @OnClick(R.id.fileDownload2) public void fileDownload2(View view) { Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull final ObservableEmitter e) throws Exception { String etString = etUrl.getText().toString(); String url = TextUtils.isEmpty(etString) ? Urls.URL_DOWNLOAD : etString; OkGo.get(url)// .headers("aaa", "111")// .params("bbb", "222")// .execute(new FileCallback() { @Override public void onSuccess(Response response) { e.onComplete(); } @Override public void onError(Response response) { e.onError(response.getException()); } @Override public void downloadProgress(Progress progress) { e.onNext(progress); } }); } })// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { btnFileDownload2.setText("正在下载中..."); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Progress progress) { String downloadLength = Formatter.formatFileSize(getApplicationContext(), progress.currentSize); String totalLength = Formatter.formatFileSize(getApplicationContext(), progress.totalSize); tvDownloadSize.setText(downloadLength + "/" + totalLength); String speed = Formatter.formatFileSize(getApplicationContext(), progress.speed); tvNetSpeed.setText(String.format("%s/s", speed)); tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); btnFileDownload2.setText("下载出错"); showToast(e.getMessage()); } @Override public void onComplete() { btnFileDownload2.setText("下载完成"); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxFormUploadActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.content.Intent; import android.os.Bundle; import android.text.format.Formatter; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.GlideImageLoader; import com.lzy.demo.utils.Urls; import com.lzy.imagepicker.ImagePicker; import com.lzy.imagepicker.bean.ImageItem; import com.lzy.imagepicker.ui.ImageGridActivity; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.convert.StringConvert; import com.lzy.okgo.model.Progress; import com.lzy.okgo.model.Response; import com.lzy.okrx2.adapter.ObservableResponse; import java.io.File; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxFormUploadActivity extends BaseRxDetailActivity { @Bind(R.id.formUpload1) Button btnFormUpload1; @Bind(R.id.formUpload2) Button btnFormUpload2; @Bind(R.id.downloadSize) TextView tvDownloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView tvNetSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; @Bind(R.id.images) TextView tvImages; private List imageItems; private NumberFormat numberFormat; @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_rx_form_upload); ButterKnife.bind(this); setTitle("文件上传"); numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.selectImage) public void selectImage(View view) { ImagePicker imagePicker = ImagePicker.getInstance(); imagePicker.setImageLoader(new GlideImageLoader()); imagePicker.setMultiMode(true); //多选 imagePicker.setShowCamera(true); //显示拍照按钮 imagePicker.setSelectLimit(9); //最多选择9张 imagePicker.setCrop(false); //不进行裁剪 Intent intent = new Intent(this, ImageGridActivity.class); startActivityForResult(intent, 100); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == ImagePicker.RESULT_CODE_ITEMS) { if (data != null && requestCode == 100) { //noinspection unchecked imageItems = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS); if (imageItems != null && imageItems.size() > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < imageItems.size(); i++) { if (i == imageItems.size() - 1) sb.append("图片").append(i + 1).append(" : ").append(imageItems.get(i).path); else sb.append("图片").append(i + 1).append(" : ").append(imageItems.get(i).path).append("\n"); } tvImages.setText(sb.toString()); } else { tvImages.setText("--"); } } else { Toast.makeText(this, "没有选择图片", Toast.LENGTH_SHORT).show(); tvImages.setText("--"); } } } @OnClick(R.id.formUpload1) public void formUpload1(View view) { ArrayList files = new ArrayList<>(); if (imageItems != null && imageItems.size() > 0) { for (int i = 0; i < imageItems.size(); i++) { files.add(new File(imageItems.get(i).path)); } } //拼接参数 OkGo.post(Urls.URL_FORM_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// .headers("header2", "headerValue2")// .params("param1", "paramValue1")// .params("param2", "paramValue2")// // .params("file1",new File("文件路径")) // .params("file2",new File("文件路径")) // .params("file3",new File("文件路径")) .addFileParams("file", files)// .converter(new StringConvert())// .adapt(new ObservableResponse())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { btnFormUpload1.setText("正在上传中...\n使用Rx方式做进度监听稍显麻烦,推荐使用方式2"); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Response response) { btnFormUpload1.setText("上传完成"); handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); btnFormUpload1.setText("上传出错"); showToast(e.getMessage()); handleError(null); } @Override public void onComplete() { } }); } @OnClick(R.id.formUpload2) public void formUpload2(View view) { final ArrayList files = new ArrayList<>(); if (imageItems != null && imageItems.size() > 0) { for (int i = 0; i < imageItems.size(); i++) { files.add(new File(imageItems.get(i).path)); } } Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull final ObservableEmitter e) throws Exception { OkGo.post(Urls.URL_FORM_UPLOAD)// .tag(this)// .headers("header1", "headerValue1")// .headers("header2", "headerValue2")// .params("param1", "paramValue1")// .params("param2", "paramValue2")// //.params("file1",new File("文件路径")) //.params("file2",new File("文件路径")) //.params("file3",new File("文件路径")) .addFileParams("file", files)// .execute(new StringCallback() { @Override public void onSuccess(Response response) { e.onComplete(); } @Override public void onError(Response response) { e.onError(response.getException()); } @Override public void uploadProgress(Progress progress) { e.onNext(progress); } }); } })// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { btnFormUpload2.setText("正在上传中..."); } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull Progress progress) { System.out.println("uploadProgress: " + progress); String downloadLength = Formatter.formatFileSize(getApplicationContext(), progress.currentSize); String totalLength = Formatter.formatFileSize(getApplicationContext(), progress.totalSize); tvDownloadSize.setText(downloadLength + "/" + totalLength); String speed = Formatter.formatFileSize(getApplicationContext(), progress.speed); tvNetSpeed.setText(String.format("%s/s", speed)); tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); btnFormUpload2.setText("上传出错"); showToast(e.getMessage()); } @Override public void onComplete() { btnFormUpload2.setText("上传完成"); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxRetrofitActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.os.Bundle; import android.view.View; import com.google.gson.reflect.TypeToken; import com.lzy.demo.R; import com.lzy.demo.base.BaseRxDetailActivity; import com.lzy.demo.model.LzyResponse; import com.lzy.demo.model.ServerModel; import com.lzy.demo.utils.Urls; import java.lang.reflect.Type; import java.util.List; import butterknife.ButterKnife; import butterknife.OnClick; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class RxRetrofitActivity extends BaseRxDetailActivity { @Override protected void onActivityCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_rx_retrofit); ButterKnife.bind(this); setTitle("统一管理请求"); } @Override protected void onDestroy() { super.onDestroy(); //Activity销毁时,取消网络请求 dispose(); } @OnClick(R.id.retrofitRequest) public void retrofitRequest(View view) { ServerApi.getString("aaa", "bbb")// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .observeOn(AndroidSchedulers.mainThread()) // .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull String s) { handleResponse(s); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.jsonRequest) public void jsonRequest(View view) { Type type = new TypeToken>() {}.getType(); ServerApi.>getData(type, Urls.URL_JSONOBJECT, "aaa", "bbb")// .subscribeOn(Schedulers.io())// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .map(new Function, ServerModel>() { @Override public ServerModel apply(@NonNull LzyResponse response) throws Exception { return response.data; } })// .observeOn(AndroidSchedulers.mainThread()) // .subscribe(new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull ServerModel response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } @OnClick(R.id.jsonArrayRequest) public void jsonArrayRequest(View view) { Type type = new TypeToken>>() {}.getType(); ServerApi.>>getData(type, Urls.URL_JSONARRAY, "aaa", "bbb")// .doOnSubscribe(new Consumer() { @Override public void accept(@NonNull Disposable disposable) throws Exception { showLoading(); } })// .map(new Function>, List>() { @Override public List apply(@NonNull LzyResponse> response) throws Exception { return response.data; } })// .observeOn(AndroidSchedulers.mainThread())// .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { addDisposable(d); } @Override public void onNext(@NonNull List response) { handleResponse(response); } @Override public void onError(@NonNull Throwable e) { e.printStackTrace(); //请求失败 showToast("请求失败"); handleError(null); } @Override public void onComplete() { dismissLoading(); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/RxUtils.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import com.lzy.demo.callback.JsonConvert; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.HttpHeaders; import com.lzy.okgo.model.HttpMethod; import com.lzy.okgo.model.HttpParams; import com.lzy.okgo.request.base.Request; import com.lzy.okrx2.adapter.ObservableBody; import java.lang.reflect.Type; import io.reactivex.Observable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/5/28 * 描 述: * 修订历史: * ================================================ */ public class RxUtils { public static Observable request(HttpMethod method, String url, Type type) { return request(method, url, type, null); } public static Observable request(HttpMethod method, String url, Type type, HttpParams params) { return request(method, url, type, params, null); } public static Observable request(HttpMethod method, String url, Type type, HttpParams params, HttpHeaders headers) { return request(method, url, type, null, params, headers); } public static Observable request(HttpMethod method, String url, Class clazz) { return request(method, url, clazz, null); } public static Observable request(HttpMethod method, String url, Class clazz, HttpParams params) { return request(method, url, clazz, params, null); } public static Observable request(HttpMethod method, String url, Class clazz, HttpParams params, HttpHeaders headers) { return request(method, url, null, clazz, params, headers); } /** * 这个封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 * 这个封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 * 这个封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 */ public static Observable request(HttpMethod method, String url, Type type, Class clazz, HttpParams params, HttpHeaders headers) { Request request; if (method == HttpMethod.GET) request = OkGo.get(url); else if (method == HttpMethod.POST) request = OkGo.post(url); else if (method == HttpMethod.PUT) request = OkGo.put(url); else if (method == HttpMethod.DELETE) request = OkGo.delete(url); else if (method == HttpMethod.HEAD) request = OkGo.head(url); else if (method == HttpMethod.PATCH) request = OkGo.patch(url); else if (method == HttpMethod.OPTIONS) request = OkGo.options(url); else if (method == HttpMethod.TRACE) request = OkGo.trace(url); else request = OkGo.get(url); request.headers(headers); request.params(params); if (type != null) { request.converter(new JsonConvert(type)); } else if (clazz != null) { request.converter(new JsonConvert(clazz)); } else { request.converter(new JsonConvert()); } return request.adapt(new ObservableBody()); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okrx2/ServerApi.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okrx2; import android.graphics.Bitmap; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.convert.BitmapConvert; import com.lzy.okgo.convert.FileConvert; import com.lzy.okgo.model.HttpHeaders; import com.lzy.okgo.model.HttpMethod; import com.lzy.okgo.model.HttpParams; import com.lzy.okgo.model.Response; import com.lzy.okrx2.adapter.ObservableResponse; import java.io.File; import java.lang.reflect.Type; import io.reactivex.Observable; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/30 * 描 述: * 修订历史: * ================================================ */ public class ServerApi { public static Observable getString(String header, String param) { HttpHeaders headers = new HttpHeaders(); headers.put("aaa", header); HttpParams params = new HttpParams(); params.put("bbb", param); //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 return RxUtils.request(HttpMethod.GET, Urls.URL_METHOD, String.class, params, headers); } public static Observable getData(Type type, String url, String header, String param) { HttpHeaders headers = new HttpHeaders(); headers.put("aaa", header); HttpParams params = new HttpParams(); params.put("bbb", param); //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 //这个RxUtils的封装其实没有必要,只是有些人喜欢这么干,我就多此一举写出来了。。 return RxUtils.request(HttpMethod.POST, url, type, params, headers); } public static Observable> getBitmap(String header, String param) { return OkGo.post(Urls.URL_IMAGE)// .headers("aaa", header)// .params("bbb", param)// .converter(new BitmapConvert())// .adapt(new ObservableResponse()); } public static Observable> getFile(String header, String param) { return OkGo.get(Urls.URL_DOWNLOAD)// .headers("aaa", header)// .params("bbb", param)// .converter(new FileConvert())// .adapt(new ObservableResponse()); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/LogUploadListener.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import com.lzy.okgo.model.Progress; import com.lzy.okserver.upload.UploadListener; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/7 * 描 述: * 修订历史: * ================================================ */ public class LogUploadListener extends UploadListener { public LogUploadListener() { super("LogUploadListener"); } @Override public void onStart(Progress progress) { System.out.println("onStart: " + progress); } @Override public void onProgress(Progress progress) { System.out.println("onProgress: " + progress); } @Override public void onError(Progress progress) { System.out.println("onError: " + progress); progress.exception.printStackTrace(); } @Override public void onFinish(T t, Progress progress) { System.out.println("onFinish: " + progress); } @Override public void onRemove(Progress progress) { System.out.println("onRemove: " + progress); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/OkUploadFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.content.Intent; import com.lzy.demo.base.MainFragment; import com.lzy.demo.model.ItemModel; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/9 * 描 述: * 修订历史: * ================================================ */ public class OkUploadFragment extends MainFragment { @Override public void fillData(List items) { items.add(new ItemModel("开始上传",// "1. 这个属于OkServer依赖中的功能,并不属于OkGo\n" +// "2. 只是简单上传管理,不支持断点上传或者分片上传\n" +// "3. 支持自定义上传任务优先级\n" +// "4. 支持链试调用\n" +// "5. 最多支持扩展3个额外数据")); items.add(new ItemModel("所有任务",// "1. 每个任务支持停止,重新上传,删除等操作\n" +// "2. 支持全部停止,全部开始,全部删除\n" +// "3. 支持全局上传任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按上传中列表和上传完成列表筛选")); items.add(new ItemModel("上传中任务",// "1. 每个任务支持停止,重新上传,删除等操作\n" +// "2. 支持全部停止,全部开始,全部删除\n" +// "3. 支持全局上传任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按上传中列表和上传完成列表筛选")); items.add(new ItemModel("已完成任务",// "1. 每个任务支持停止,重新上传,删除等操作\n" +// "2. 支持全部停止,全部开始,全部删除\n" +// "3. 支持全局上传任务监听\n" +// "4. 支持一个任务多个监听\n" +// "5. 支持按上传中列表和上传完成列表筛选")); } @Override public void onItemClick(int position) { if (position == 0) startActivity(new Intent(context, UploadListActivity.class)); if (position == 1) startActivity(new Intent(context, UploadAllActivity.class)); if (position == 2) startActivity(new Intent(context, UploadingActivity.class)); if (position == 3) startActivity(new Intent(context, UploadFinishActivity.class)); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/UploadAdapter.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.text.format.Formatter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.lzy.demo.R; import com.lzy.demo.ui.NumberProgressBar; import com.lzy.demo.utils.Urls; import com.lzy.imagepicker.bean.ImageItem; import com.lzy.okgo.OkGo; import com.lzy.okgo.convert.StringConvert; import com.lzy.okgo.db.UploadManager; import com.lzy.okgo.model.Progress; import com.lzy.okgo.request.PostRequest; import com.lzy.okgo.request.base.Request; import com.lzy.okserver.OkUpload; import com.lzy.okserver.upload.UploadListener; import com.lzy.okserver.upload.UploadTask; import java.io.File; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2017/6/5 * 描 述: * 修订历史: * ================================================ */ public class UploadAdapter extends RecyclerView.Adapter { public static final int TYPE_ALL = 0; public static final int TYPE_FINISH = 1; public static final int TYPE_ING = 2; private List> values; private List images; private NumberFormat numberFormat; private LayoutInflater inflater; private Context context; private int type = -1; public UploadAdapter(Context context) { this.context = context; numberFormat = NumberFormat.getPercentInstance(); numberFormat.setMinimumFractionDigits(2); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void updateData(int type) { //这里是将数据库的数据恢复 this.type = type; if (type == TYPE_ALL) values = OkUpload.restore(UploadManager.getInstance().getAll()); if (type == TYPE_FINISH) values = OkUpload.restore(UploadManager.getInstance().getFinished()); if (type == TYPE_ING) values = OkUpload.restore(UploadManager.getInstance().getUploading()); //由于Converter是无法保存下来的,所以这里恢复任务的时候,需要额外传入Converter,否则就没法解析数据 //至于数据类型,统一就行,不一定非要是String for (UploadTask task : values) { //noinspection unchecked Request request = (Request) task.progress.request; request.converter(new StringConvert()); } notifyDataSetChanged(); } public List> updateData(List images) { this.type = -1; this.images = images; values = new ArrayList<>(); if (images != null) { Random random = new Random(); for (int i = 0; i < images.size(); i++) { ImageItem imageItem = images.get(i); //这里是演示可以传递任何数据 PostRequest postRequest = OkGo.post(Urls.URL_FORM_UPLOAD)// .headers("aaa", "111")// .params("bbb", "222")// .params("fileKey" + i, new File(imageItem.path))// .converter(new StringConvert()); UploadTask task = OkUpload.request(imageItem.path, postRequest)// .priority(random.nextInt(100))// .extra1(imageItem)// .save(); values.add(task); } } notifyDataSetChanged(); return values; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.item_upload_manager, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { //noinspection unchecked UploadTask task = (UploadTask) values.get(position); String tag = createTag(task); task.register(new ListUploadListener(tag, holder))// .register(new LogUploadListener()); holder.setTag(tag); holder.setTask(task); holder.bind(); holder.refresh(task.progress); } public void unRegister() { Map> taskMap = OkUpload.getInstance().getTaskMap(); for (UploadTask task : taskMap.values()) { task.unRegister(createTag(task)); } } private String createTag(UploadTask task) { return type + "_" + task.progress.tag; } @Override public int getItemCount() { return values == null ? 0 : values.size(); } public class ViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.icon) ImageView icon; @Bind(R.id.name) TextView name; @Bind(R.id.priority) TextView priority; @Bind(R.id.downloadSize) TextView downloadSize; @Bind(R.id.tvProgress) TextView tvProgress; @Bind(R.id.netSpeed) TextView netSpeed; @Bind(R.id.pbProgress) NumberProgressBar pbProgress; @Bind(R.id.upload) Button upload; private UploadTask task; private String tag; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } public void setTask(UploadTask task) { this.task = task; } public void bind() { Progress progress = task.progress; ImageItem item = (ImageItem) progress.extra1; Glide.with(context).load(item.path).error(R.mipmap.ic_launcher).into(icon); name.setText(item.name); priority.setText(String.format("优先级:%s", progress.priority)); } public void refresh(Progress progress) { String currentSize = Formatter.formatFileSize(context, progress.currentSize); String totalSize = Formatter.formatFileSize(context, progress.totalSize); downloadSize.setText(currentSize + "/" + totalSize); priority.setText(String.format("优先级:%s", progress.priority)); switch (progress.status) { case Progress.NONE: netSpeed.setText("停止"); upload.setText("上传"); break; case Progress.PAUSE: netSpeed.setText("暂停中"); upload.setText("继续"); break; case Progress.ERROR: netSpeed.setText("上传出错"); upload.setText("出错"); break; case Progress.WAITING: netSpeed.setText("等待中"); upload.setText("等待"); break; case Progress.FINISH: upload.setText("完成"); netSpeed.setText("上传成功"); break; case Progress.LOADING: String speed = Formatter.formatFileSize(context, progress.speed); netSpeed.setText(String.format("%s/s", speed)); upload.setText("停止"); break; } tvProgress.setText(numberFormat.format(progress.fraction)); pbProgress.setMax(10000); pbProgress.setProgress((int) (progress.fraction * 10000)); } @OnClick(R.id.upload) public void upload() { Progress progress = task.progress; switch (progress.status) { case Progress.PAUSE: case Progress.NONE: case Progress.ERROR: task.start(); break; case Progress.LOADING: task.pause(); break; case Progress.FINISH: break; } refresh(progress); } @OnClick(R.id.remove) public void remove() { task.remove(); if (type == -1) { int removeIndex = -1; for (int i = 0; i < images.size(); i++) { if (images.get(i).path.equals(task.progress.tag)) { removeIndex = i; break; } } if (removeIndex != -1) { images.remove(removeIndex); } updateData(images); } else { updateData(type); } } @OnClick(R.id.restart) public void restart() { task.restart(); } public void setTag(String tag) { this.tag = tag; } public String getTag() { return tag; } } private class ListUploadListener extends UploadListener { private ViewHolder holder; ListUploadListener(Object tag, ViewHolder holder) { super(tag); this.holder = holder; } @Override public void onStart(Progress progress) { } @Override public void onProgress(Progress progress) { if (tag == holder.getTag()) { holder.refresh(progress); } } @Override public void onError(Progress progress) { Throwable throwable = progress.exception; if (throwable != null) throwable.printStackTrace(); } @Override public void onFinish(String s, Progress progress) { Toast.makeText(context, "上传完成", Toast.LENGTH_SHORT).show(); if (type != -1) updateData(type); } @Override public void onRemove(Progress progress) { } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/UploadAllActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkUpload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class UploadAllActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Bind(R.id.select) Button select; @Bind(R.id.upload) Button upload; @Bind(R.id.deleteAll) Button deleteAll; private OkUpload okUpload; private UploadAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_upload_list); initToolBar(toolbar, true, "所有任务"); select.setVisibility(View.GONE); upload.setVisibility(View.GONE); deleteAll.setVisibility(View.VISIBLE); okUpload = OkUpload.getInstance(); okUpload.getThreadPool().setCorePoolSize(1); adapter = new UploadAdapter(this); adapter.updateData(UploadAdapter.TYPE_ALL); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okUpload.addOnAllTaskEndListener(this); } @Override protected void onDestroy() { super.onDestroy(); okUpload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override public void onAllTaskEnd() { showToast("所有上传任务已结束"); } @OnClick(R.id.deleteAll) public void deleteAll(View view) { OkUpload.getInstance().removeAll(); adapter.updateData(UploadAdapter.TYPE_ALL); adapter.notifyDataSetChanged(); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/UploadFinishActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkUpload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class UploadFinishActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Bind(R.id.select) Button select; @Bind(R.id.upload) Button upload; private OkUpload okUpload; private UploadAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_upload_list); initToolBar(toolbar, true, "已完成任务"); select.setVisibility(View.GONE); upload.setVisibility(View.GONE); okUpload = OkUpload.getInstance(); okUpload.getThreadPool().setCorePoolSize(1); adapter = new UploadAdapter(this); adapter.updateData(UploadAdapter.TYPE_FINISH); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okUpload.addOnAllTaskEndListener(this); } @Override protected void onDestroy() { super.onDestroy(); okUpload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override public void onAllTaskEnd() { showToast("所有上传任务已结束"); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/UploadListActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.utils.GlideImageLoader; import com.lzy.imagepicker.ImagePicker; import com.lzy.imagepicker.bean.ImageItem; import com.lzy.imagepicker.ui.ImageGridActivity; import com.lzy.okserver.OkUpload; import com.lzy.okserver.task.XExecutor; import com.lzy.okserver.upload.UploadTask; import java.util.List; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class UploadListActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; private UploadAdapter adapter; private OkUpload okUpload; private List> tasks; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_upload_list); initToolBar(toolbar, true, "开始上传"); okUpload = OkUpload.getInstance(); okUpload.getThreadPool().setCorePoolSize(1); adapter = new UploadAdapter(this); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okUpload.addOnAllTaskEndListener(this); } @Override protected void onDestroy() { super.onDestroy(); okUpload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override public void onAllTaskEnd() { showToast("所有上传任务已结束"); } @OnClick(R.id.select) public void select(View view) { ImagePicker imagePicker = ImagePicker.getInstance(); imagePicker.setImageLoader(new GlideImageLoader()); imagePicker.setShowCamera(true); imagePicker.setSelectLimit(9); imagePicker.setCrop(false); Intent intent = new Intent(getApplicationContext(), ImageGridActivity.class); startActivityForResult(intent, 100); } @OnClick(R.id.upload) public void upload(View view) { if (tasks == null) { showToast("请先选择图片"); return; } for (UploadTask task : tasks) { task.start(); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == ImagePicker.RESULT_CODE_ITEMS) { if (data != null && requestCode == 100) { //noinspection unchecked List images = (List) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS); tasks = adapter.updateData(images); } else { showToast("没有数据"); } } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/okupload/UploadingActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.okupload; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Button; import com.lzy.demo.R; import com.lzy.demo.base.BaseActivity; import com.lzy.okserver.OkUpload; import com.lzy.okserver.task.XExecutor; import butterknife.Bind; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class UploadingActivity extends BaseActivity implements XExecutor.OnAllTaskEndListener { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Bind(R.id.select) Button select; @Bind(R.id.upload) Button upload; private OkUpload okUpload; private UploadAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_upload_list); initToolBar(toolbar, true, "上传中任务"); select.setVisibility(View.GONE); upload.setVisibility(View.GONE); okUpload = OkUpload.getInstance(); okUpload.getThreadPool().setCorePoolSize(1); adapter = new UploadAdapter(this); adapter.updateData(UploadAdapter.TYPE_ING); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); okUpload.addOnAllTaskEndListener(this); } @Override protected void onDestroy() { super.onDestroy(); okUpload.removeOnAllTaskEndListener(this); adapter.unRegister(); } @Override public void onAllTaskEnd() { showToast("所有上传任务已结束"); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/supercache/NewsAdapter.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.supercache; import android.view.View; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.lzy.demo.R; import com.lzy.demo.WebActivity; import com.lzy.demo.model.GankModel; import com.lzy.ninegrid.ImageInfo; import com.lzy.ninegrid.NineGridView; import com.lzy.ninegrid.preview.NineGridViewClickAdapter; import java.util.ArrayList; import java.util.List; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/8/17 * 描 述: * 修订历史: * ================================================ */ public class NewsAdapter extends BaseQuickAdapter { public NewsAdapter(List data) { super(R.layout.item_news, data); } @Override protected void convert(BaseViewHolder baseViewHolder, final GankModel model) { baseViewHolder.setText(R.id.title, model.desc)// .setText(R.id.desc, model.desc)// .setText(R.id.pubDate, model.publishedAt.toString())// .setText(R.id.source, model.source); View view = baseViewHolder.getConvertView(); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WebActivity.runActivity(mContext, model.desc, model.url); } }); NineGridView nineGrid = baseViewHolder.getView(R.id.nineGrid); ArrayList imageInfo = new ArrayList<>(); if (model.images != null) { for (String image : model.images) { ImageInfo info = new ImageInfo(); info.setThumbnailUrl(image); info.setBigImageUrl(image); imageInfo.add(info); } } nineGrid.setAdapter(new NineGridViewClickAdapter(mContext, imageInfo)); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/supercache/NewsCallback.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.supercache; import com.google.gson.stream.JsonReader; import com.lzy.demo.model.GankResponse; import com.lzy.demo.utils.Convert; import com.lzy.okgo.callback.AbsCallback; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Response; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/1 * 描 述: * 修订历史: * ================================================ */ public abstract class NewsCallback extends AbsCallback { /** * 这里的数据解析是根据 http://gank.io/api/data/Android/10/1 返回的数据来写的 * 实际使用中,自己服务器返回的数据格式和上面网站肯定不一样,所以以下是参考代码,根据实际情况自己改写 */ @Override public T convertResponse(Response response) throws Throwable { //以下代码是通过泛型解析实际参数,泛型必须传 Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); Type type = params[0]; if (!(type instanceof ParameterizedType)) throw new IllegalStateException("没有填写泛型参数"); JsonReader jsonReader = new JsonReader(response.body().charStream()); Type rawType = ((ParameterizedType) type).getRawType(); if (rawType == GankResponse.class) { GankResponse gankResponse = Convert.fromJson(jsonReader, type); if (!gankResponse.error) { response.close(); //noinspection unchecked return (T) gankResponse; } else { response.close(); throw new IllegalStateException("服务端接口错误"); } } else { response.close(); throw new IllegalStateException("基类错误无法解析!"); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/supercache/NewsTabFragment.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.supercache; import android.content.Context; import android.graphics.Color; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.chad.library.adapter.base.BaseQuickAdapter; import com.lzy.demo.R; import com.lzy.demo.base.BaseFragment; import com.lzy.demo.model.GankModel; import com.lzy.demo.model.GankResponse; import com.lzy.demo.utils.Urls; import com.lzy.okgo.OkGo; import com.lzy.okgo.cache.CacheMode; import com.lzy.okgo.model.Response; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class NewsTabFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { private static final int PAGE_SIZE = 20; @Bind(R.id.recyclerView) RecyclerView recyclerView; @Bind(R.id.refreshLayout) SwipeRefreshLayout refreshLayout; private Context context; private int currentPage = 2; private NewsAdapter newsAdapter; private String url; private boolean isInitCache = false; public static NewsTabFragment newInstance() { return new NewsTabFragment(); } @Override public void onAttach(Context context) { this.context = context; super.onAttach(context); } @Override protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.item_refresh, container, false); ButterKnife.bind(this, view); return view; } @Override protected void initData() { url = Urls.URL_GANK_BASE + fragmentTitle + "/" + PAGE_SIZE + "/"; recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setLayoutManager(new LinearLayoutManager(context)); newsAdapter = new NewsAdapter(null); newsAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN); newsAdapter.isFirstOnly(false); recyclerView.setAdapter(newsAdapter); refreshLayout.setColorSchemeColors(Color.RED, Color.BLUE, Color.GREEN); refreshLayout.setOnRefreshListener(this); newsAdapter.setOnLoadMoreListener(this); //开启loading,获取数据 setRefreshing(true); onRefresh(); } /** 下拉刷新 */ @Override public void onRefresh() { OkGo.>>get(url + "1")// .cacheKey("TabFragment_" + fragmentTitle) //由于该fragment会被复用,必须保证key唯一,否则数据会发生覆盖 .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST) //缓存模式先使用缓存,然后使用网络数据 .execute(new NewsCallback>>() { @Override public void onSuccess(Response>> response) { List results = response.body().results; if (results != null) { currentPage = 2; newsAdapter.setNewData(results); } } @Override public void onCacheSuccess(Response>> response) { //一般来说,只需呀第一次初始化界面的时候需要使用缓存刷新界面,以后不需要,所以用一个变量标识 if (!isInitCache) { //一般来说,缓存回调成功和网络回调成功做的事情是一样的,所以这里直接回调onSuccess onSuccess(response); isInitCache = true; } } @Override public void onError(Response>> response) { //网络请求失败的回调,一般会弹个Toast showToast(response.getException().getMessage()); } @Override public void onFinish() { //可能需要移除之前添加的布局 newsAdapter.removeAllFooterView(); //最后调用结束刷新的方法 setRefreshing(false); } }); } /** 上拉加载 */ @Override public void onLoadMoreRequested() { OkGo.>>get(url + currentPage)// .cacheMode(CacheMode.NO_CACHE) //上拉不需要缓存 .execute(new NewsCallback>>() { @Override public void onSuccess(Response>> response) { List results = response.body().results; if (results != null && results.size() > 0) { currentPage++; newsAdapter.addData(results); } else { //显示没有更多数据 newsAdapter.loadComplete(); View noDataView = inflater.inflate(R.layout.item_no_data, (ViewGroup) recyclerView.getParent(), false); newsAdapter.addFooterView(noDataView); } } @Override public void onError(Response>> response) { //显示数据加载失败,点击重试 newsAdapter.showLoadMoreFailedView(); //网络请求失败的回调,一般会弹个Toast showToast(response.getException().getMessage()); } }); } public void showToast(String msg) { Snackbar.make(recyclerView, msg, Snackbar.LENGTH_SHORT).show(); } public void setRefreshing(final boolean refreshing) { refreshLayout.post(new Runnable() { @Override public void run() { refreshLayout.setRefreshing(refreshing); } }); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/supercache/SuperCacheActivity.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.supercache; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; import android.view.View; import com.lzy.demo.R; import com.lzy.demo.WebActivity; import com.lzy.demo.base.BaseActivity; import com.lzy.demo.utils.GlideImageLoader; import com.lzy.ninegrid.NineGridView; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.OnClick; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class SuperCacheActivity extends BaseActivity { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.viewPager) ViewPager viewPager; @Bind(R.id.tab) TabLayout tab; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_super_cache); initToolBar(toolbar, true, "强大的缓存"); NineGridView.setImageLoader(new GlideImageLoader()); ArrayList fragments = new ArrayList<>(); NewsTabFragment fragment1 = NewsTabFragment.newInstance(); fragment1.setTitle("Android"); fragments.add(fragment1); NewsTabFragment fragment2 = NewsTabFragment.newInstance(); fragment2.setTitle("iOS"); fragments.add(fragment2); NewsTabFragment fragment3 = NewsTabFragment.newInstance(); fragment3.setTitle("前端"); fragments.add(fragment3); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragments); viewPager.setAdapter(adapter); viewPager.setOffscreenPageLimit(fragments.size()); tab.setupWithViewPager(viewPager); } @OnClick(R.id.fab) public void fab(View view) { WebActivity.runActivity(this, "我的Github,欢迎star", "https://github.com/jeasonlzy"); } public class MyPagerAdapter extends FragmentPagerAdapter { private List fragments; public MyPagerAdapter(FragmentManager fm, List fragments) { super(fm); this.fragments = fragments; } @Override public CharSequence getPageTitle(int position) { return fragments.get(position).getTitle(); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/ui/NumberProgressBar.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.ui; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.view.View; import com.lzy.demo.R; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class NumberProgressBar extends View { public interface OnProgressBarListener { void onProgressChange(int current, int max); } private int mMaxProgress = 100; /** * Current progress, can not exceed the max progress. */ private int mCurrentProgress = 0; /** * The progress area bar color. */ private int mReachedBarColor; /** * The bar unreached area color. */ private int mUnreachedBarColor; /** * The progress text color. */ private int mTextColor; /** * The progress text size. */ private float mTextSize; /** * The height of the reached area. */ private float mReachedBarHeight; /** * The height of the unreached area. */ private float mUnreachedBarHeight; /** * The suffix of the number. */ private String mSuffix = "%"; /** * The prefix. */ private String mPrefix = ""; private final int default_text_color = Color.rgb(66, 145, 241); private final int default_reached_color = Color.rgb(66, 145, 241); private final int default_unreached_color = Color.rgb(204, 204, 204); private final float default_progress_text_offset; private final float default_text_size; private final float default_reached_bar_height; private final float default_unreached_bar_height; /** * For save and restore instance of progressbar. */ private static final String INSTANCE_STATE = "saved_instance"; private static final String INSTANCE_TEXT_COLOR = "text_color"; private static final String INSTANCE_TEXT_SIZE = "text_size"; private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height"; private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color"; private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height"; private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color"; private static final String INSTANCE_MAX = "max"; private static final String INSTANCE_PROGRESS = "progress"; private static final String INSTANCE_SUFFIX = "suffix"; private static final String INSTANCE_PREFIX = "prefix"; private static final String INSTANCE_TEXT_VISIBILITY = "text_visibility"; private static final int PROGRESS_TEXT_VISIBLE = 0; /** * The width of the text that to be drawn. */ private float mDrawTextWidth; /** * The drawn text start. */ private float mDrawTextStart; /** * The drawn text end. */ private float mDrawTextEnd; /** * The text that to be drawn in onDraw(). */ private String mCurrentDrawText; /** * The Paint of the reached area. */ private Paint mReachedBarPaint; /** * The Paint of the unreached area. */ private Paint mUnreachedBarPaint; /** * The Paint of the progress text. */ private Paint mTextPaint; /** * Unreached bar area to draw rect. */ private RectF mUnreachedRectF = new RectF(0, 0, 0, 0); /** * Reached bar area rect. */ private RectF mReachedRectF = new RectF(0, 0, 0, 0); /** * The progress text offset. */ private float mOffset; /** * Determine if need to draw unreached area. */ private boolean mDrawUnreachedBar = true; private boolean mDrawReachedBar = true; private boolean mIfDrawText = true; /** * Listener */ private OnProgressBarListener mListener; public enum ProgressTextVisibility { Visible, Invisible } public NumberProgressBar(Context context) { this(context, null); } public NumberProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); default_reached_bar_height = dp2px(1.5f); default_unreached_bar_height = dp2px(1.0f); default_text_size = sp2px(10); default_progress_text_offset = dp2px(3.0f); //load styled attributes. final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar, defStyleAttr, 0); mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color); mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color, default_unreached_color); mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color, default_text_color); mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size); mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height, default_reached_bar_height); mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height, default_unreached_bar_height); mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset, default_progress_text_offset); int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility, PROGRESS_TEXT_VISIBLE); if (textVisible != PROGRESS_TEXT_VISIBLE) { mIfDrawText = false; } setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress_current, 0)); setMax(attributes.getInt(R.styleable.NumberProgressBar_progress_max, 100)); attributes.recycle(); initializePainters(); } @Override protected int getSuggestedMinimumWidth() { return (int) mTextSize; } @Override protected int getSuggestedMinimumHeight() { return Math.max((int) mTextSize, Math.max((int) mReachedBarHeight, (int) mUnreachedBarHeight)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false)); } private int measure(int measureSpec, boolean isWidth) { int result; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom(); if (mode == MeasureSpec.EXACTLY) { result = size; } else { result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight(); result += padding; if (mode == MeasureSpec.AT_MOST) { if (isWidth) { result = Math.max(result, size); } else { result = Math.min(result, size); } } } return result; } @Override protected void onDraw(Canvas canvas) { if (mIfDrawText) { calculateDrawRectF(); } else { calculateDrawRectFWithoutProgressText(); } if (mDrawReachedBar) { canvas.drawRect(mReachedRectF, mReachedBarPaint); } if (mDrawUnreachedBar) { canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint); } if (mIfDrawText) canvas.drawText(mCurrentDrawText, mDrawTextStart, mDrawTextEnd, mTextPaint); } private void initializePainters() { mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mReachedBarPaint.setColor(mReachedBarColor); mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mUnreachedBarPaint.setColor(mUnreachedBarColor); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mTextSize); } private void calculateDrawRectFWithoutProgressText() { mReachedRectF.left = getPaddingLeft(); mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f; mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft(); mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f; mUnreachedRectF.left = mReachedRectF.right; mUnreachedRectF.right = getWidth() - getPaddingRight(); mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f; mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f; } private void calculateDrawRectF() { mCurrentDrawText = String.format("%d", getProgress() * 100 / getMax()); mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix; mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText); if (getProgress() == 0) { mDrawReachedBar = false; mDrawTextStart = getPaddingLeft(); } else { mDrawReachedBar = true; mReachedRectF.left = getPaddingLeft(); mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f; mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() - mOffset + getPaddingLeft(); mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f; mDrawTextStart = (mReachedRectF.right + mOffset); } mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)); if ((mDrawTextStart + mDrawTextWidth) >= getWidth() - getPaddingRight()) { mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth; mReachedRectF.right = mDrawTextStart - mOffset; } float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset; if (unreachedBarStart >= getWidth() - getPaddingRight()) { mDrawUnreachedBar = false; } else { mDrawUnreachedBar = true; mUnreachedRectF.left = unreachedBarStart; mUnreachedRectF.right = getWidth() - getPaddingRight(); mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f; mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f; } } /** * Get progress text color. * * @return progress text color. */ public int getTextColor() { return mTextColor; } /** * Get progress text size. * * @return progress text size. */ public float getProgressTextSize() { return mTextSize; } public int getUnreachedBarColor() { return mUnreachedBarColor; } public int getReachedBarColor() { return mReachedBarColor; } public int getProgress() { return mCurrentProgress; } public int getMax() { return mMaxProgress; } public float getReachedBarHeight() { return mReachedBarHeight; } public float getUnreachedBarHeight() { return mUnreachedBarHeight; } public void setProgressTextSize(float textSize) { this.mTextSize = textSize; mTextPaint.setTextSize(mTextSize); invalidate(); } public void setProgressTextColor(int textColor) { this.mTextColor = textColor; mTextPaint.setColor(mTextColor); invalidate(); } public void setUnreachedBarColor(int barColor) { this.mUnreachedBarColor = barColor; mUnreachedBarPaint.setColor(mUnreachedBarColor); invalidate(); } public void setReachedBarColor(int progressColor) { this.mReachedBarColor = progressColor; mReachedBarPaint.setColor(mReachedBarColor); invalidate(); } public void setReachedBarHeight(float height) { mReachedBarHeight = height; } public void setUnreachedBarHeight(float height) { mUnreachedBarHeight = height; } public void setMax(int maxProgress) { if (maxProgress > 0) { this.mMaxProgress = maxProgress; invalidate(); } } public void setSuffix(String suffix) { if (suffix == null) { mSuffix = ""; } else { mSuffix = suffix; } } public String getSuffix() { return mSuffix; } public void setPrefix(String prefix) { if (prefix == null) mPrefix = ""; else { mPrefix = prefix; } } public String getPrefix() { return mPrefix; } public void incrementProgressBy(int by) { if (by > 0) { setProgress(getProgress() + by); } if (mListener != null) { mListener.onProgressChange(getProgress(), getMax()); } } public void setProgress(int progress) { if (progress <= getMax() && progress >= 0) { this.mCurrentProgress = progress; invalidate(); } } @Override protected Parcelable onSaveInstanceState() { final Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState()); bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor()); bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize()); bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT, getReachedBarHeight()); bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT, getUnreachedBarHeight()); bundle.putInt(INSTANCE_REACHED_BAR_COLOR, getReachedBarColor()); bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR, getUnreachedBarColor()); bundle.putInt(INSTANCE_MAX, getMax()); bundle.putInt(INSTANCE_PROGRESS, getProgress()); bundle.putString(INSTANCE_SUFFIX, getSuffix()); bundle.putString(INSTANCE_PREFIX, getPrefix()); bundle.putBoolean(INSTANCE_TEXT_VISIBILITY, getProgressTextVisibility()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { final Bundle bundle = (Bundle) state; mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR); mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE); mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT); mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT); mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR); mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR); initializePainters(); setMax(bundle.getInt(INSTANCE_MAX)); setProgress(bundle.getInt(INSTANCE_PROGRESS)); setPrefix(bundle.getString(INSTANCE_PREFIX)); setSuffix(bundle.getString(INSTANCE_SUFFIX)); setProgressTextVisibility(bundle.getBoolean(INSTANCE_TEXT_VISIBILITY) ? ProgressTextVisibility.Visible : ProgressTextVisibility.Invisible); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE)); return; } super.onRestoreInstanceState(state); } public float dp2px(float dp) { final float scale = getResources().getDisplayMetrics().density; return dp * scale + 0.5f; } public float sp2px(float sp) { final float scale = getResources().getDisplayMetrics().scaledDensity; return sp * scale; } public void setProgressTextVisibility(ProgressTextVisibility visibility) { mIfDrawText = visibility == ProgressTextVisibility.Visible; invalidate(); } public boolean getProgressTextVisibility() { return mIfDrawText; } public void setOnProgressBarListener(OnProgressBarListener listener) { mListener = listener; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/ui/ProgressPieView.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.ui; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.support.v4.util.LruCache; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import com.lzy.demo.R; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ public class ProgressPieView extends View { public interface OnProgressListener { public void onProgressChanged(int progress, int max); public void onProgressCompleted(); } /** * Fills the progress radially in a clockwise direction. */ public static final int FILL_TYPE_RADIAL = 0; /** * Fills the progress expanding from the center of the view. */ public static final int FILL_TYPE_CENTER = 1; public static final int SLOW_ANIMATION_SPEED = 50; public static final int MEDIUM_ANIMATION_SPEED = 25; public static final int FAST_ANIMATION_SPEED = 1; private static final int DEFAULT_MAX = 100; private static final int DEFAULT_PROGRESS = 0; private static final int DEFAULT_START_ANGLE = -90; private static final float DEFAULT_STROKE_WIDTH = 3f; private static final float DEFAULT_TEXT_SIZE = 14f; private static final int DEFAULT_VIEW_SIZE = 96; private static LruCache sTypefaceCache = new LruCache(8); private OnProgressListener mListener; private DisplayMetrics mDisplayMetrics; private int mMax = DEFAULT_MAX; private int mProgress = DEFAULT_PROGRESS; private int mStartAngle = DEFAULT_START_ANGLE; private boolean mInverted = false; private boolean mCounterclockwise = false; private boolean mShowStroke = true; private float mStrokeWidth = DEFAULT_STROKE_WIDTH; private boolean mShowText = true; private float mTextSize = DEFAULT_TEXT_SIZE; private String mText; private String mTypeface; private boolean mShowImage = true; private Drawable mImage; private Rect mImageRect; private Paint mStrokePaint; private Paint mTextPaint; private Paint mProgressPaint; private Paint mBackgroundPaint; private RectF mInnerRectF; private int mProgressFillType = FILL_TYPE_RADIAL; private int mAnimationSpeed = MEDIUM_ANIMATION_SPEED; private AnimationHandler mAnimationHandler = new AnimationHandler(); private int mViewSize; public ProgressPieView(Context context) { this(context, null); } public ProgressPieView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ProgressPieView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mDisplayMetrics = context.getResources().getDisplayMetrics(); mStrokeWidth = mStrokeWidth * mDisplayMetrics.density; mTextSize = mTextSize * mDisplayMetrics.scaledDensity; final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressPieView); final Resources res = getResources(); mMax = a.getInteger(R.styleable.ProgressPieView_ppvMax, mMax); mProgress = a.getInteger(R.styleable.ProgressPieView_ppvProgress, mProgress); mStartAngle = a.getInt(R.styleable.ProgressPieView_ppvStartAngle, mStartAngle); mInverted = a.getBoolean(R.styleable.ProgressPieView_ppvInverted, mInverted); mCounterclockwise = a.getBoolean(R.styleable.ProgressPieView_ppvCounterclockwise, mCounterclockwise); mStrokeWidth = a.getDimension(R.styleable.ProgressPieView_ppvStrokeWidth, mStrokeWidth); mTypeface = a.getString(R.styleable.ProgressPieView_ppvTypeface); mTextSize = a.getDimension(R.styleable.ProgressPieView_android_textSize, mTextSize); mText = a.getString(R.styleable.ProgressPieView_android_text); mShowStroke = a.getBoolean(R.styleable.ProgressPieView_ppvShowStroke, mShowStroke); mShowText = a.getBoolean(R.styleable.ProgressPieView_ppvShowText, mShowText); mImage = a.getDrawable(R.styleable.ProgressPieView_ppvImage); int backgroundColor = Color.parseColor("#00000000"); backgroundColor = a.getColor(R.styleable.ProgressPieView_ppvBackgroundColor, backgroundColor); int progressColor = Color.parseColor("#33b5e5"); progressColor = a.getColor(R.styleable.ProgressPieView_ppvProgressColor, progressColor); int strokeColor = Color.parseColor("#33b5e5"); strokeColor = a.getColor(R.styleable.ProgressPieView_ppvStrokeColor, strokeColor); int textColor = Color.parseColor("#333333"); textColor = a.getColor(R.styleable.ProgressPieView_android_textColor, textColor); mProgressFillType = a.getInteger(R.styleable.ProgressPieView_ppvProgressFillType, mProgressFillType); a.recycle(); mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBackgroundPaint.setColor(backgroundColor); mBackgroundPaint.setStyle(Paint.Style.FILL); mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mProgressPaint.setColor(progressColor); mProgressPaint.setStyle(Paint.Style.FILL); mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mStrokePaint.setColor(strokeColor); mStrokePaint.setStyle(Paint.Style.STROKE); mStrokePaint.setStrokeWidth(mStrokeWidth); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(textColor); mTextPaint.setTextSize(mTextSize); mTextPaint.setTextAlign(Paint.Align.CENTER); mInnerRectF = new RectF(); mImageRect = new Rect(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = resolveSize(DEFAULT_VIEW_SIZE, widthMeasureSpec); int height = resolveSize(DEFAULT_VIEW_SIZE, heightMeasureSpec); mViewSize = Math.min(width, height); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mInnerRectF.set(0, 0, mViewSize, mViewSize); mInnerRectF.offset((getWidth() - mViewSize) / 2, (getHeight() - mViewSize) / 2); if (mShowStroke) { final int halfBorder = (int) (mStrokePaint.getStrokeWidth() / 2f + 0.5f); mInnerRectF.inset(halfBorder, halfBorder); } float centerX = mInnerRectF.centerX(); float centerY = mInnerRectF.centerY(); canvas.drawArc(mInnerRectF, 0, 360, true, mBackgroundPaint); switch (mProgressFillType) { case FILL_TYPE_RADIAL: float sweepAngle = 360 * mProgress / mMax; if (mInverted) { sweepAngle = sweepAngle - 360; } if (mCounterclockwise) { sweepAngle = -sweepAngle; } canvas.drawArc(mInnerRectF, mStartAngle, sweepAngle, true, mProgressPaint); break; case FILL_TYPE_CENTER: float radius = (mViewSize / 2) * ((float) mProgress / mMax); if (mShowStroke) { radius = radius + 0.5f - mStrokePaint.getStrokeWidth(); } canvas.drawCircle(centerX, centerY, radius, mProgressPaint); break; default: throw new IllegalArgumentException("Invalid Progress Fill = " + mProgressFillType); } if (!TextUtils.isEmpty(mText) && mShowText) { if (!TextUtils.isEmpty(mTypeface)) { Typeface typeface = sTypefaceCache.get(mTypeface); if (null == typeface && null != getResources()) { AssetManager assets = getResources().getAssets(); if (null != assets) { typeface = Typeface.createFromAsset(assets, mTypeface); sTypefaceCache.put(mTypeface, typeface); } } mTextPaint.setTypeface(typeface); } int xPos = (int) centerX; int yPos = (int) (centerY - (mTextPaint.descent() + mTextPaint.ascent()) / 2); canvas.drawText(mText, xPos, yPos, mTextPaint); } if (null != mImage && mShowImage) { int drawableSize = mImage.getIntrinsicWidth(); mImageRect.set(0, 0, drawableSize, drawableSize); mImageRect.offset((getWidth() - drawableSize) / 2, (getHeight() - drawableSize) / 2); mImage.setBounds(mImageRect); mImage.draw(canvas); } if (mShowStroke) { canvas.drawOval(mInnerRectF, mStrokePaint); } } /** * Gets the maximum progress value. */ public int getMax() { return mMax; } /** * Sets the maximum progress value. Defaults to 100. */ public void setMax(int max) { if (max <= 0 || max < mProgress) { throw new IllegalArgumentException(String.format("Max (%d) must be > 0 and >= %d", max, mProgress)); } mMax = max; invalidate(); } /** * Sets the animation speed used in the animateProgressFill method. */ public void setAnimationSpeed(int animationSpeed) { this.mAnimationSpeed = animationSpeed; } /** * Returns the current animation speed used in animateProgressFill method. */ public int getAnimationSpeed() { return this.mAnimationSpeed; } /** * Animates a progress fill of the view, using a Handler. */ public void animateProgressFill() { mAnimationHandler.removeMessages(0); mAnimationHandler.setAnimateTo(mMax); mAnimationHandler.sendEmptyMessage(0); invalidate(); } /** * Animates a progress fill of the view, using a Handler. * * @param animateTo - the progress value the animation should stop at (0 - MAX) */ public void animateProgressFill(int animateTo) { mAnimationHandler.removeMessages(0); if (animateTo > mMax || animateTo < 0) { throw new IllegalArgumentException(String.format("Animation progress (%d) is greater than the max progress (%d) or lower than 0 ", animateTo, mMax)); } mAnimationHandler.setAnimateTo(animateTo); mAnimationHandler.sendEmptyMessage(0); invalidate(); } /** * Stops the views animation. */ public void stopAnimating() { mAnimationHandler.removeMessages(0); mAnimationHandler.setAnimateTo(mProgress); invalidate(); } /** * Gets the current progress from 0 to max. */ public int getProgress() { return mProgress; } /** * Sets the current progress (must be between 0 and max). */ public void setProgress(int progress) { if (progress > mMax || progress < 0) { throw new IllegalArgumentException(String.format("Progress (%d) must be between %d and %d", progress, 0, mMax)); } mProgress = progress; if (null != mListener) { if (mProgress == mMax) { mListener.onProgressCompleted(); } else { mListener.onProgressChanged(mProgress, mMax); } } invalidate(); } /** * Gets the start angle the {@link #FILL_TYPE_RADIAL} uses. */ public int getStartAngle() { return mStartAngle; } /** * Sets the start angle the {@link #FILL_TYPE_RADIAL} uses. * * @param startAngle start angle in degrees */ public void setStartAngle(int startAngle) { mStartAngle = startAngle; } /** * Gets the inverted state. */ public boolean isInverted() { return mInverted; } /** * Sets the inverted state. * * @param inverted draw the progress inverted or not */ public void setInverted(boolean inverted) { mInverted = inverted; } /** * Gets the counterclockwise state. */ public boolean isCounterclockwise() { return mCounterclockwise; } /** * Sets the counterclockwise state. * * @param counterclockwise draw the progress counterclockwise or not */ public void setCounterclockwise(boolean counterclockwise) { mCounterclockwise = counterclockwise; } /** * Gets the color used to display the progress of the view. */ public int getProgressColor() { return mProgressPaint.getColor(); } /** * Sets the color used to display the progress of the view. * * @param color - color of the progress part of the view */ public void setProgressColor(int color) { mProgressPaint.setColor(color); invalidate(); } /** * Gets the color used to display the background of the view. */ public int getBackgroundColor() { return mBackgroundPaint.getColor(); } /** * Sets the color used to display the background of the view. * * @param color - color of the background part of the view */ public void setBackgroundColor(int color) { mBackgroundPaint.setColor(color); invalidate(); } /** * Gets the color used to display the text of the view. */ public int getTextColor() { return mTextPaint.getColor(); } /** * Sets the color used to display the text of the view. * * @param color - color of the text part of the view */ public void setTextColor(int color) { mTextPaint.setColor(color); invalidate(); } /** * Gets the text size in sp. */ public float getTextSize() { return mTextSize; } /** * Sets the text size. * * @param sizeSp in sp for the text */ public void setTextSize(int sizeSp) { mTextSize = sizeSp * mDisplayMetrics.scaledDensity; mTextPaint.setTextSize(mTextSize); invalidate(); } /** * Gets the text of the view. */ public String getText() { return mText; } /** * Sets the text of the view. * * @param text to be displayed in the view */ public void setText(String text) { mText = text; invalidate(); } /** * Gets the typeface of the text. */ public String getTypeface() { return mTypeface; } /** * Sets the text typeface. * - i.printStackTrace. fonts/Roboto/Roboto-Regular.ttf * * @param typeface that the text is displayed in */ public void setTypeface(String typeface) { mTypeface = typeface; invalidate(); } /** * Gets the show text state. */ public boolean isTextShowing() { return mShowText; } /** * Sets the show text state. * * @param showText show or hide text */ public void setShowText(boolean showText) { mShowText = showText; invalidate(); } /** * Get the color used to display the stroke of the view. */ public int getStrokeColor() { return mStrokePaint.getColor(); } /** * Sets the color used to display the stroke of the view. * * @param color - color of the stroke part of the view */ public void setStrokeColor(int color) { mStrokePaint.setColor(color); invalidate(); } /** * Gets the stroke width in dp. */ public float getStrokeWidth() { return mStrokeWidth; } /** * Set the stroke width. * * @param widthDp in dp for the pie border */ public void setStrokeWidth(int widthDp) { mStrokeWidth = widthDp * mDisplayMetrics.density; mStrokePaint.setStrokeWidth(mStrokeWidth); invalidate(); } /** * Gets the show stroke state. */ public boolean isStrokeShowing() { return mShowStroke; } /** * Sets the show stroke state. * * @param showStroke show or hide stroke */ public void setShowStroke(boolean showStroke) { mShowStroke = showStroke; invalidate(); } /** * Gets the drawable of the view. */ public Drawable getImageDrawable() { return mImage; } /** * Sets the drawable of the view. * * @param image drawable of the view */ public void setImageDrawable(Drawable image) { mImage = image; invalidate(); } /** * Sets the drawable of the view. * * @param resId resource id of the view's drawable */ public void setImageResource(int resId) { if (null != getResources()) { mImage = getResources().getDrawable(resId); invalidate(); } } /** * Gets the show image state. */ public boolean isImageShowing() { return mShowImage; } /** * Sets the show image state. * * @param showImage show or hide image */ public void setShowImage(boolean showImage) { mShowImage = showImage; invalidate(); } /** * Gets the progress fill type. */ public int getProgressFillType() { return mProgressFillType; } /** * Sets the progress fill type. * * @param fillType one of {@link #FILL_TYPE_CENTER}, {@link #FILL_TYPE_RADIAL} */ public void setProgressFillType(int fillType) { mProgressFillType = fillType; } /** * Sets the progress listner. * * @param listener progress listener */ public void setOnProgressListener(OnProgressListener listener) { mListener = listener; } /** * Handler used to perform the fill animation. */ private class AnimationHandler extends Handler { private int mAnimateTo; public void setAnimateTo(int animateTo) { mAnimateTo = animateTo; } @Override public void handleMessage(Message msg) { if (mProgress > mAnimateTo) { setProgress(mProgress - 1); sendEmptyMessageDelayed(0, mAnimationSpeed); } else if (mProgress < mAnimateTo) { setProgress(mProgress + 1); sendEmptyMessageDelayed(0, mAnimationSpeed); } else { removeMessages(0); } } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/ui/SimpleViewBehavior.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.ui; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.util.AttributeSet; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; import com.lzy.demo.R; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/11 * 描 述: * 修订历史: * ================================================ */ @SuppressWarnings("unused") public class SimpleViewBehavior extends CoordinatorLayout.Behavior { private static final int UNSPECIFIED_INT = Integer.MAX_VALUE; private static final float UNSPECIFIED_FLOAT = Float.MAX_VALUE; private static final int DEPEND_TYPE_HEIGHT = 0; private static final int DEPEND_TYPE_WIDTH = 1; private static final int DEPEND_TYPE_X = 2; private static final int DEPEND_TYPE_Y = 3; private int mDependViewId = 0; //默认没有依赖对象 private int mDependType = DEPEND_TYPE_Y; //默认按照y方向变化 private int mDependTargetX; //X方向的允许最大距离(影响动画percent) private int mDependTargetY; //Y方向的允许最大距离(影响动画percent) private int mDependTargetWidth; //依赖控件起始最大宽度(影响动画percent) private int mDependTargetHeight; //依赖控件起始最大高度(影响动画percent) private int targetX; private int targetY; private int targetWidth; private int targetHeight; private int targetBackgroundColor; private float targetAlpha; private float targetRotateX; private float targetRotateY; private int mAnimationId = 0; //自定义动画id(xml文件定义动画) private int mDependStartX; private int mDependStartY; private int mDependStartWidth; private int mDependStartHeight; private int mStartX; private int mStartY; private int mStartWidth; private int mStartHeight; private int mStartBackgroundColor; private float mStartAlpha; private float mStartRotateX; private float mStartRotateY; private Animation mAnimation; private boolean isPrepared; public SimpleViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SimpleViewBehavior); mDependViewId = a.getResourceId(R.styleable.SimpleViewBehavior_svb_dependOn, mDependViewId); mDependType = a.getInt(R.styleable.SimpleViewBehavior_svb_dependType, mDependType); mDependTargetX = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_dependTargetX, UNSPECIFIED_INT); mDependTargetY = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_dependTargetY, UNSPECIFIED_INT); mDependTargetWidth = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_dependTargetWidth, UNSPECIFIED_INT); mDependTargetHeight = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_dependTargetHeight, UNSPECIFIED_INT); targetX = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_targetX, UNSPECIFIED_INT); targetY = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_targetY, UNSPECIFIED_INT); targetWidth = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_targetWidth, UNSPECIFIED_INT); targetHeight = a.getDimensionPixelOffset(R.styleable.SimpleViewBehavior_svb_targetHeight, UNSPECIFIED_INT); targetBackgroundColor = a.getColor(R.styleable.SimpleViewBehavior_svb_targetBackgroundColor, UNSPECIFIED_INT); targetAlpha = a.getFloat(R.styleable.SimpleViewBehavior_svb_targetAlpha, UNSPECIFIED_FLOAT); targetRotateX = a.getFloat(R.styleable.SimpleViewBehavior_svb_targetRotateX, UNSPECIFIED_FLOAT); targetRotateY = a.getFloat(R.styleable.SimpleViewBehavior_svb_targetRotateY, UNSPECIFIED_FLOAT); mAnimationId = a.getResourceId(R.styleable.SimpleViewBehavior_svb_animation, mAnimationId); a.recycle(); } /** 初始化数据 */ private void prepare(CoordinatorLayout parent, View child, View dependency) { mDependStartX = (int) dependency.getX(); mDependStartY = (int) dependency.getY(); mDependStartWidth = dependency.getWidth(); mDependStartHeight = dependency.getHeight(); mStartX = (int) child.getX(); mStartY = (int) child.getY(); mStartWidth = child.getWidth(); mStartHeight = child.getHeight(); mStartAlpha = child.getAlpha(); mStartRotateX = child.getRotationX(); mStartRotateY = child.getRotationY(); //特殊处理y方向变化 if (mDependTargetY == UNSPECIFIED_INT && dependency instanceof AppBarLayout) { mDependTargetY = ((AppBarLayout) dependency).getTotalScrollRange(); } // 背景颜色渐变 if (child.getBackground() instanceof ColorDrawable) mStartBackgroundColor = ((ColorDrawable) child.getBackground()).getColor(); // 自定义动画 if (mAnimationId != 0) { mAnimation = AnimationUtils.loadAnimation(child.getContext(), mAnimationId); mAnimation.initialize(child.getWidth(), child.getHeight(), parent.getWidth(), parent.getHeight()); } // 兼容5.0以上的沉浸模式 if (Build.VERSION.SDK_INT > 16 && parent.getFitsSystemWindows() && targetY != UNSPECIFIED_INT) { targetY += getStatusBarHeight(parent.getContext()); } isPrepared = true; } /** * child 是指应用behavior的View ,dependency 担任触发behavior的角色,并与child进行互动。 * layoutDependsOn方法在每次layout发生变化时都会调用,我们需要在dependency控件发生变化时返回True, * 在我们的例子中是用户在屏幕上滑动时(因为AppBarLayout发生了移动),然后我们需要让child做出相应的反应。 */ @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency.getId() == mDependViewId; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { // 该方法会在滑动的时候一直回调,但只需要初始化一次 if (!isPrepared) prepare(parent, child, dependency); updateView(child, dependency); return false; } /** * 这个是CoordinatorLayout在进行measure的过程中,利用Behavior对象对子view进行大小测量的一个方法。 * 在这个方法内,我们可以通过parent.getDependencies(child);这个方法,获取到这个child依赖的view,然后通过获取这个child依赖的view的大小来决定自身的大小。 */ @Override public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } /** * 这个方法是用来子view用来布局自身使用,如果依赖其他view,那么系统会首先调用 * public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) * 这个方法,可以在这个回调中记录dependency的一些位置信息,在onLayoutChild中利用保存下来的信息进行计算,然后得到自身的具体位置。 */ @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { boolean bool = super.onLayoutChild(parent, child, layoutDirection); if (isPrepared) updateView(child, parent.getDependencies(child).get(0)); return bool; } public void updateView(View child, View dependency) { float percent = 0; float start = 0; float current = 0; float end = UNSPECIFIED_INT; switch (mDependType) { case DEPEND_TYPE_WIDTH: start = mDependStartWidth; current = dependency.getWidth(); end = mDependTargetWidth; break; case DEPEND_TYPE_HEIGHT: start = mDependStartHeight; current = dependency.getHeight(); end = mDependTargetHeight; break; case DEPEND_TYPE_X: start = mDependStartX; current = dependency.getX(); end = mDependTargetX; break; case DEPEND_TYPE_Y: start = mDependStartY; current = dependency.getY(); end = mDependTargetY; break; } if (end != UNSPECIFIED_INT) { percent = Math.abs(current - start) / Math.abs(end - start); } updateViewWithPercent(child, percent > 1 ? 1 : percent); } /** 更新View */ public void updateViewWithPercent(View child, float percent) { if (mAnimation == null) { //如果没有自定义动画,那么使用属性动画 float newX = targetX == UNSPECIFIED_INT ? 0 : (targetX - mStartX) * percent; float newY = targetY == UNSPECIFIED_INT ? 0 : (targetY - mStartY) * percent; //缩放动画 if (targetWidth != UNSPECIFIED_INT || targetHeight != UNSPECIFIED_INT) { child.setScaleX(scaleEvaluator(mStartWidth, targetWidth, percent)); child.setScaleY(scaleEvaluator(mStartHeight, targetHeight, percent)); float newWidth = floatEvaluator(mStartWidth, targetWidth, percent); float newHeight = floatEvaluator(mStartWidth, targetWidth, percent); newX -= (mStartWidth - newWidth) / 2; newY -= (mStartHeight - newHeight) / 2; } //平移动画 child.setTranslationX(newX); child.setTranslationY(newY); //透明度变化 if (targetAlpha != UNSPECIFIED_FLOAT) child.setAlpha(floatEvaluator(mStartAlpha, targetAlpha, percent)); //背景渐变 if (targetBackgroundColor != UNSPECIFIED_INT && mStartBackgroundColor != 0) { child.setBackgroundColor(argbEvaluator(mStartBackgroundColor, targetBackgroundColor, percent)); } //旋转动画 if (targetRotateX != UNSPECIFIED_FLOAT) child.setRotationX(floatEvaluator(mStartRotateX, targetRotateX, percent)); if (targetRotateY != UNSPECIFIED_FLOAT) child.setRotationY(floatEvaluator(mStartRotateY, targetRotateY, percent)); } else { mAnimation.setStartTime(0); mAnimation.restrictDuration(100); Transformation transformation = new Transformation(); mAnimation.getTransformation((long) (percent * 100), transformation); BehaviorAnimation animation = new BehaviorAnimation(transformation); child.startAnimation(animation); } child.requestLayout(); } private static class BehaviorAnimation extends Animation { private Transformation mTransformation; public BehaviorAnimation(Transformation transformation) { mTransformation = transformation; setDuration(0); setFillAfter(true); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { t.compose(mTransformation); super.applyTransformation(interpolatedTime, t); } } public static float floatEvaluator(float originalSize, float finalSize, float percent) { return (finalSize - originalSize) * percent + originalSize; } public static float scaleEvaluator(float originalSize, float finalSize, float percent) { float calcSize = (finalSize - originalSize) * percent + originalSize; return calcSize / originalSize; } public static int argbEvaluator(int startColor, int endColor, float percent) { int startA = (startColor >> 24) & 0xff; int startR = (startColor >> 16) & 0xff; int startG = (startColor >> 8) & 0xff; int startB = startColor & 0xff; int endA = (endColor >> 24) & 0xff; int endR = (endColor >> 16) & 0xff; int endG = (endColor >> 8) & 0xff; int endB = endColor & 0xff; return ((startA + (int) (percent * (endA - startA))) << 24) |// ((startR + (int) (percent * (endR - startR))) << 16) |// ((startG + (int) (percent * (endG - startG))) << 8) |// ((startB + (int) (percent * (endB - startB)))); } /** 获取状态栏的高度 */ private static int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/ui/TranslateUpDownBehavior.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.ui; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorListener; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import com.lzy.demo.utils.AnimHelper; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/8/17 * 描 述: * 修订历史: * ================================================ */ @SuppressWarnings("unused") public class TranslateUpDownBehavior extends FloatingActionButton.Behavior { private boolean isAnimating = false; private OnStateChangeListener listener; public TranslateUpDownBehavior(Context context, AttributeSet attrs) { super(); } public static TranslateUpDownBehavior form(View view) { ViewGroup.LayoutParams params = view.getLayoutParams(); if (params == null || !(params instanceof CoordinatorLayout.LayoutParams)) { throw new IllegalArgumentException("parent must be CoordinatorLayout"); } CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params).getBehavior(); if (!(behavior instanceof TranslateUpDownBehavior)) { throw new IllegalArgumentException("the behavior must be TranslateUpDownBehavior"); } return (TranslateUpDownBehavior) behavior; } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { if (((dyConsumed > 0 && dyUnconsumed == 0) || (dyConsumed == 0 && dyUnconsumed > 0)) && !isAnimating && child.getVisibility() == View.VISIBLE) { if (listener != null) listener.onChange(true); AnimHelper.translateDown(child, new MyViewPropertyAnimatorListener() { @Override public void onAnimationEnd(View view) { super.onAnimationEnd(view); view.setVisibility(View.INVISIBLE); } }); } else if ((dyConsumed < 0 && dyUnconsumed == 0) || (dyConsumed == 0 && dyUnconsumed < 0) && !isAnimating && child.getVisibility() == View.INVISIBLE) { if (listener != null) listener.onChange(false); child.setVisibility(View.VISIBLE); AnimHelper.translateUp(child, null); } } private class MyViewPropertyAnimatorListener implements ViewPropertyAnimatorListener { @Override public void onAnimationStart(View view) { isAnimating = true; } @Override public void onAnimationEnd(View view) { isAnimating = false; } @Override public void onAnimationCancel(View view) { isAnimating = false; } } public void setOnStateChangeListener(OnStateChangeListener listener) { this.listener = listener; } public interface OnStateChangeListener { void onChange(boolean isUp); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/AnimHelper.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import android.content.Context; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorListener; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/8/17 * 描 述: * 修订历史: * ================================================ */ public class AnimHelper { private AnimHelper() { throw new RuntimeException("AnimHelper cannot be initialized!"); } public static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); public static final int DURATION = 300; public static void scaleShow(View view, ViewPropertyAnimatorListener listener) { ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).alpha(1.0f).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static void scaleHide(View view, ViewPropertyAnimatorListener listener) { ViewCompat.animate(view).scaleX(0f).scaleY(0f).alpha(0f).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static void alphaShow(View view, ViewPropertyAnimatorListener listener) { ViewCompat.animate(view).alpha(1.0f).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static void alphaHide(View view, ViewPropertyAnimatorListener listener) { ViewCompat.animate(view).alpha(0f).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static void translateUp(View view, ViewPropertyAnimatorListener listener) { ViewCompat.animate(view).translationY(0).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static void translateDown(View view, ViewPropertyAnimatorListener listener) { int height = view.getHeight(); ViewGroup.LayoutParams params = view.getLayoutParams(); ViewGroup.MarginLayoutParams layoutParams = params instanceof ViewGroup.MarginLayoutParams ? ((ViewGroup.MarginLayoutParams) params) : null; if (layoutParams != null) height += layoutParams.bottomMargin; ViewCompat.animate(view).translationY(height).setDuration(DURATION).setListener(listener).setInterpolator(INTERPOLATOR).withLayer().start(); } public static float floatEvaluator(float originalSize, float finalSize, float percent) { return (finalSize - originalSize) * percent + originalSize; } public static int argbEvaluator(int startColor, int endColor, float percent) { int startA = (startColor >> 24) & 0xff; int startR = (startColor >> 16) & 0xff; int startG = (startColor >> 8) & 0xff; int startB = startColor & 0xff; int endA = (endColor >> 24) & 0xff; int endR = (endColor >> 16) & 0xff; int endG = (endColor >> 8) & 0xff; int endB = endColor & 0xff; return ((startA + (int) (percent * (endA - startA))) << 24) | ((startR + (int) (percent * (endR - startR))) << 16) | ((startG + (int) (percent * (endG - startG))) << 8) | ((startB + (int) (percent * (endB - startB)))); } public static float scaleEvaluator(float originalSize, float finalSize, float percent) { float calcSize = (finalSize - originalSize) * percent + originalSize; return calcSize / originalSize; } /** 获得状态栏的高度 */ public static int getStatusBarHeight(Context context) { int statusHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/ApkUtils.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2016/1/25 * 描 述: * 修订历史: * ================================================ */ public class ApkUtils { /** 安装一个apk文件 */ public static void install(Context context, File uriFile) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(uriFile), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } /** 卸载一个app */ public static void uninstall(Context context, String packageName) { //通过程序的包名创建URI Uri packageURI = Uri.parse("package:" + packageName); //创建Intent意图 Intent intent = new Intent(Intent.ACTION_DELETE, packageURI); //执行卸载程序 context.startActivity(intent); } /** 检查手机上是否安装了指定的软件 */ public static boolean isAvailable(Context context, String packageName) { // 获取packagemanager final PackageManager packageManager = context.getPackageManager(); // 获取所有已安装程序的包信息 List packageInfos = packageManager.getInstalledPackages(0); // 用于存储所有已安装程序的包名 List packageNames = new ArrayList<>(); // 从pinfo中将包名字逐一取出,压入pName list中 if (packageInfos != null) { for (int i = 0; i < packageInfos.size(); i++) { String packName = packageInfos.get(i).packageName; packageNames.add(packName); } } // 判断packageNames中是否有目标程序的包名,有TRUE,没有FALSE return packageNames.contains(packageName); } /** 检查手机上是否安装了指定的软件 */ public static boolean isAvailable(Context context, File file) { return isAvailable(context, getPackageName(context, file.getAbsolutePath())); } /** 根据文件路径获取包名 */ public static String getPackageName(Context context, String filePath) { PackageManager packageManager = context.getPackageManager(); PackageInfo info = packageManager.getPackageArchiveInfo(filePath, PackageManager.GET_ACTIVITIES); if (info != null) { ApplicationInfo appInfo = info.applicationInfo; return appInfo.packageName; //得到安装包名称 } return null; } /** 从apk中获取版本信息 */ public static String getChannelFromApk(Context context, String channelPrefix) { //从apk包中获取 ApplicationInfo appinfo = context.getApplicationInfo(); String sourceDir = appinfo.sourceDir; //默认放在meta-inf/里, 所以需要再拼接一下 String key = "META-INF/" + channelPrefix; String ret = ""; ZipFile zipfile = null; try { zipfile = new ZipFile(sourceDir); Enumeration entries = zipfile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = ((ZipEntry) entries.nextElement()); String entryName = entry.getName(); if (entryName.startsWith(key)) { ret = entryName; break; } } } catch (IOException e) { e.printStackTrace(); } finally { if (zipfile != null) { try { zipfile.close(); } catch (IOException e) { e.printStackTrace(); } } } String[] split = ret.split(channelPrefix); String channel = ""; if (split.length >= 2) { channel = ret.substring(key.length()); } return channel; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/ColorUtils.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils;/** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2015/8/4 * 描 述: * 修订历史: * ================================================ */ import android.graphics.Color; import java.util.Random; public class ColorUtils { public static int randomColor() { Random random = new Random(); int red = random.nextInt(150) + 50; int green = random.nextInt(150) + 50; int blue = random.nextInt(150) + 50; return Color.rgb(red, green, blue); } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/Convert.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonIOException; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.readystatesoftware.chuck.internal.support.JsonConvertor; import java.io.Reader; import java.lang.reflect.Type; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/28 * 描 述: * 修订历史: * ================================================ */ public class Convert { private static Gson create() { return Convert.GsonHolder.gson; } private static class GsonHolder { private static Gson gson = new Gson(); } public static T fromJson(String json, Class type) throws JsonIOException, JsonSyntaxException { return create().fromJson(json, type); } public static T fromJson(String json, Type type) { return create().fromJson(json, type); } public static T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { return create().fromJson(reader, typeOfT); } public static T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { return create().fromJson(json, classOfT); } public static T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { return create().fromJson(json, typeOfT); } public static String toJson(Object src) { return create().toJson(src); } public static String toJson(Object src, Type typeOfSrc) { return create().toJson(src, typeOfSrc); } public static String formatJson(String json) { try { JsonParser jp = new JsonParser(); JsonElement je = jp.parse(json); return JsonConvertor.getInstance().toJson(je); } catch (Exception e) { return json; } } public static String formatJson(Object src) { try { JsonParser jp = new JsonParser(); JsonElement je = jp.parse(toJson(src)); return JsonConvertor.getInstance().toJson(je); } catch (Exception e) { return e.getMessage(); } } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/GlideImageLoader.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.lzy.demo.R; import com.lzy.imagepicker.loader.ImageLoader; import com.lzy.ninegrid.NineGridView; import java.io.File; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/5 * 描 述: * 修订历史: * ================================================ */ public class GlideImageLoader implements ImageLoader, NineGridView.ImageLoader { @Override public void onDisplayImage(Context context, ImageView imageView, String url) { Glide.with(context).load(url)// .placeholder(R.drawable.ic_default_color)// 这行貌似是glide的bug,在部分机型上会导致第一次图片不在中间 .error(R.drawable.ic_default_color)// .diskCacheStrategy(DiskCacheStrategy.SOURCE)// .into(imageView); } @Override public Bitmap getCacheImage(String url) { return null; } @Override public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) { Glide.with(activity).load(new File(path))// .placeholder(R.drawable.ic_default_color)// .error(R.drawable.ic_default_color)// .diskCacheStrategy(DiskCacheStrategy.SOURCE)// .into(imageView); } @Override public void clearMemoryCache() { } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/MD5Utils.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import java.io.File; import java.io.FileInputStream; import java.security.DigestInputStream; import java.security.MessageDigest; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:2015/10/11 * 描 述:MD5加密工具类 * 修订历史: * ================================================ */ public class MD5Utils { private MD5Utils() { } /** * 获取字符串的 MD5 */ public static String encode(String str) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(str.getBytes("UTF-8")); byte messageDigest[] = md5.digest(); StringBuilder hexString = new StringBuilder(); for (byte b : messageDigest) { hexString.append(String.format("%02X", b)); } return hexString.toString().toLowerCase(); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 获取文件的 MD5 */ public static String encode(File file) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); FileInputStream inputStream = new FileInputStream(file); DigestInputStream digestInputStream = new DigestInputStream(inputStream, messageDigest); //必须把文件读取完毕才能拿到md5 byte[] buffer = new byte[4096]; while (digestInputStream.read(buffer) > -1) { } MessageDigest digest = digestInputStream.getMessageDigest(); digestInputStream.close(); byte[] md5 = digest.digest(); StringBuilder sb = new StringBuilder(); for (byte b : md5) { sb.append(String.format("%02X", b)); } return sb.toString().toLowerCase(); } catch (Exception e) { e.printStackTrace(); } return null; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/PicassoImageLoader.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.net.Uri; import android.widget.ImageView; import com.lzy.imagepicker.loader.ImageLoader; import com.lzy.ninegrid.NineGridView; import com.lzy.demo.R; import com.squareup.picasso.Picasso; import java.io.File; /** * ================================================ * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy * 版 本:1.0 * 创建日期:16/9/1 * 描 述: * 修订历史: * ================================================ */ public class PicassoImageLoader implements ImageLoader, NineGridView.ImageLoader { @Override public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) { Picasso.with(activity) //配置上下文 .load(Uri.fromFile(new File(path))) //设置图片路径(fix #8,文件名包含%符号 无法识别和显示) .error(R.drawable.ic_default_color) //设置错误图片 .placeholder(R.drawable.ic_default_color) //设置占位图片 .into(imageView); } @Override public void clearMemoryCache() { } @Override public void onDisplayImage(Context context, ImageView imageView, String url) { Picasso.with(context).load(url)// .placeholder(R.drawable.ic_default_color)// .error(R.drawable.ic_default_color)// .into(imageView); } @Override public Bitmap getCacheImage(String url) { return null; } } ================================================ FILE: demo/src/main/java/com/lzy/demo/utils/Urls.java ================================================ /* * Copyright 2016 jeasonlzy(廖子尧) * * 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. */ package com.lzy.demo.utils; /** * ================================================ * 作 者:jeasonlzy(廖子尧) * 版 本:1.0 * 创建日期:2016/4/6 * 描 述:我的Github地址 https://github.com/jeasonlzy * 修订历史: * ================================================ */ public class Urls { public static final String SERVER = "http://server.jeasonlzy.com/OkHttpUtils/"; // public static final String SERVER = "http://192.168.1.121:8080/OkHttpUtils/"; public static final String URL_METHOD = SERVER + "method"; public static final String URL_CACHE = SERVER + "cache"; public static final String URL_IMAGE = SERVER + "image"; public static final String URL_JSONOBJECT = SERVER + "jsonObject"; public static final String URL_JSONARRAY = SERVER + "jsonArray"; public static final String URL_FORM_UPLOAD = SERVER + "upload"; public static final String URL_TEXT_UPLOAD = SERVER + "uploadString"; public static final String URL_DOWNLOAD = SERVER + "download"; public static final String URL_REDIRECT = SERVER + "redirect"; public static final String URL_GANK_BASE = "http://gank.io/api/data/"; } ================================================ FILE: demo/src/main/res/drawable/progress_bar_states.xml ================================================ ================================================ FILE: demo/src/main/res/layout/activity_base.xml ================================================ ================================================ FILE: demo/src/main/res/layout/activity_bitmap_request.xml ================================================