├── .gitignore ├── LICENSE ├── README.md ├── README_EN.md ├── application ├── Meizhi Android之RxJava & Retrofit最佳实践.md └── README.md ├── library └── README.md ├── task.md └── view └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac system files 2 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android 优质开源项目剖析与技术进阶 2 | 本系列的文章主要面向以下几类读者: 3 | 4 | 1. 不满足于`简单使用开源库`,想要`通过探究其原理`以`精进自身技术或创建自己的开源库`; 5 | 2. 对于`新技术`如`RxJava`等的实践处于摸索状态,希望有`优质的code实例及细致分析`来让你迅速上手一门新技术; 6 | 3. 对于一些`底层库`如`网络底层库Retrofit`、`图片加载库Picasso/Glide`等实现原理保持好奇。 7 | 8 | _________________________________ 9 | 10 | 比起阅读枯燥文档,独自摸索一门技术的最佳实践,我们还有一种方法能够快速而稳定的精进自身的开发水平,那就是通过`阅读、分析、仿写与理解`优质的开源项目。 11 | 12 | ### 一、已有文章 13 | 14 | #### Application 15 | 分析文档 | 作者 | 开源项目 | 介绍 | 添加时间 16 | :------------- | :------------- | :------------- | :------------- | :------------- 17 | [Meizhi Android之RxJava & Retrofit最佳实践](https://github.com/wingjay/android-open-source-project-cracking/blob/master/application/Meizhi%20Android%E4%B9%8BRxJava%20%26%20Retrofit%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.md) | [wingjay](https://github.com/wingjay) | [Meizhi](github.com/drakeet/Meizhi) | 使用RxJava & Retrofit的sample | 20160416 18 | 19 | #### View 20 | 分析文档 | 作者 | 开源项目 | 介绍 | 添加时间 21 | :------------- | :------------- | :------------- | :------------- | :------------- 22 | [JJSearchViewAnim源码分析](http://www.jianshu.com/p/a48f4e6cf036)| [Skykai521](https://github.com/Skykai521)| [JJSearchViewAnim](https://github.com/android-cjj/JJSearchViewAnim) | | 20160417 23 | [SwipeBackLayout源码分析](http://www.jianshu.com/p/a91d669421e9)| [Skykai521](https://github.com/Skykai521)| [SwipeBackLayout](https://github.com/ikew0ng/SwipeBackLayout) | | 20160417 24 | [HTextView源码分析](http://www.jianshu.com/p/15358d444800)| [Skykai521](https://github.com/Skykai521)| [HTextView](https://github.com/hanks-zyh/HTextView) | | 20160417 25 | 26 | #### Library 27 | 分析文档 | 作者 | 开源项目 | 介绍 | 添加时间 28 | :------------- | :------------- | :------------- | :------------- | :------------- 29 | [RxPermissions源码解析](http://www.jianshu.com/p/c8a30200e6b2)| [Skykai521](https://github.com/Skykai521)| [RxPermissions](https://github.com/tbruyelle/RxPermissions) | | 20160417 30 | [BarcodeScanner源码分析](http://www.jianshu.com/p/d34383d4cb89)| [Skykai521](https://github.com/Skykai521)| [BarcodeScanner](https://github.com/dm77/barcodescanner) | | 20160417 31 | [ViewAnimator源码分析](http://www.jianshu.com/p/749c4531d108)| [Skykai521](https://github.com/Skykai521)| [ViewAnimator](https://github.com/florent37/ViewAnimator) | | 20160417 32 | [uCrop源码分析](http://www.jianshu.com/p/523e77a10321)| [Skykai521](https://github.com/Skykai521)| [uCrop](https://github.com/Yalantis/uCrop) | | 20160417 33 | [Picasso源代分析](http://www.jianshu.com/p/3c36382bc1cd)| [Skykai521](https://github.com/Skykai521)| [Picasso](https://github.com/square/picasso) | | 20160417 34 | [EventBus 3.0源码分析](http://www.jianshu.com/p/f057c460c77e)| [Skykai521](https://github.com/Skykai521)| [EventBus](https://github.com/greenrobot/EventBus) | | 20160417 35 | 36 | ### 二、我们会挑选哪些`优质开源项目` 37 | #### 1. 新技术 38 | 我们会挑选覆盖`RxJava`、`React Native`、`Dynamic load`、`Dagger`、`Retrofit`等新技术的开源项目,分析总结出`新技术最佳实践`供读者阅读仿写,快速将新技术应用到自身项目开发中,不用反复踩坑。 39 | 40 | #### 2. 底层库 41 | 初级程序员会调用API、实现基本功能; 42 | 中级程序员开始`封装`,消除`ugly`代码; 43 | 高级程序员能够`设计架构`,重构出`优雅`代码。 44 | 45 | 我们会挑选一些优秀底层库,`深入浅出`的去分析它们的`设计思想`,阐述如何把这些设计思想融入到自身实际项目中。 46 | 47 | #### 3. 自定义View 48 | 很多人习惯了在Github寻找通用的UI库。 49 | 50 | 坏消息是,UI的变化千千万,迟早有一天我们会不得不由于自己项目的特殊性,而要自己来实现自定义view。 51 | 52 | 好消息是,自定义view虽然变化万千,但却不离其宗,而我们的分析就是尝试向你讲述`如何理解自定义view的原理`。 53 | 54 | ### 三、加入我们 55 | 如果你对本项目有兴趣,你可以选择以下方式之一加入进来: 56 | 57 | 1. `阅读者`。`start & watch`这个项目,关注微信公众号`CoolCoder`,我们会在第一时间推送。 58 | 2. `写作者`。如果你热爱分析开源项目,热爱分享与写作。那就挑选一个你认为优质的开源项目进行写作,创建pull request。 59 | 3. `评论者`。阅读中遇到问题?直接创建[issue](https://github.com/wingjay/android-open-source-project-cracking/issues),作者会快速回答你。 60 | 4. `翻译者`。如果你还不具备分析开源项目的能力,那可以来对我们的中文文章进行翻译。这个翻译过程会让你受益匪浅的。 61 | 5. `校对者`。如果你技术过硬,愿意帮助新手程序员,可以发邮件给我,我相信"校对者"三个字会让很多年轻程序员记住你。 62 | 63 | ### 四、写作者 64 | [wingjay](https://github.com/wingjay) 65 | 66 | ![](https://avatars0.githubusercontent.com/u/9619875?v=3&s=460) 67 | 68 | [达庆凯 Skykai521](https://github.com/Skykai521) 69 | 70 | ![](https://avatars3.githubusercontent.com/u/8402109?v=3&s=100) 71 | 72 | ... 73 | 74 | 75 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /application/Meizhi Android之RxJava & Retrofit最佳实践.md: -------------------------------------------------------------------------------- 1 | ## 零、背景 2 | 比起阅读枯燥的技术文档,独自苦苦摸索新技术的基本用法,还有一种更好更快速也更有效的提高自身技术的方法,那就是阅读学习优质的开源项目,通过仿写、练习最终达到理解,潜移默化提升自身编程技能。 3 | 4 | 《带你学开源项目》系列将带领你深入阅读及分析当前流行的一些开源项目,并针对其中采用的新技术与精妙之处进行细致的阐述,以期让你快速掌握Android开发中的多种强大技能点。 5 | 6 | ## 一、本期开源项目Meizhi Android 7 | 本次的开源项目选择了[Meizhi Android](https://github.com/drakeet/Meizhi),本文主要介绍该项目中采用的`RxJava`、`Retrofit`两种技术,这二者在Android开发者中非常流行,不仅能够`优美地处理异步回调`,而且能`提高代码的性能和稳定性`。而Meizhi Android中较好的覆盖了二者的多种应用场景,能够给多数开发者一个全面的学习。 8 | 9 | 下面本人会`对原项目的代码进行详细的介绍`,同时为了读者看的清楚其中的逻辑关系,可能会做一定调整以帮助读者理解,比如把lambda表达式还原成普通java函数形式,以避免很多读者对lambda并不熟悉。 10 | 11 | ##二、原项目分析 12 | ###0. clone项目到本地 13 | 第一步当然是把项目clone下来,编译,运行。有兴趣的同学可以执行这一步。 14 | ###1. 添加`Stetho`抓包工具 15 | 首先,由于我们要分析retrofit,所以为了查看app的网络请求,有兴趣的同学可以手动在代码里添加[Stetho](http://facebook.github.io/stetho/)。`Stetho`是Facebook推出的一款黑科技,能够在chrome里轻松查看app所有的网络请求,比起iOS需要装个[Charles](https://www.charlesproxy.com/)查看http请求方便多咯。 16 | 17 | ![Stetho使用场景](http://upload-images.jianshu.io/upload_images/281665-50854bb575db05f9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 18 | 19 | ###2. Retrofit结构 20 | 从下图我们可以看到,首页里有很多card,每一个card里有两个元素:`妹纸图片`, `描述文字`,具体UI实现我们不在乎,只要明白一点,这两个元素数据是来自于两个不同的api。其中,`妹纸图片`来自于`http://gank.io/api/data/福利/10`;`描述文字`来自于`http://gank.io/api/data/休息视频/10`。 21 | 22 | app中为了请求网络数据,采用了[Retrofit](http://square.github.io/retrofit/)。具体关于retrofit如何配置请各位参考官网,这里只讲解如何使用`Retrofit`。 23 | 24 | 该项目中主要创建了以下几个类来实现`Retrofit`结构,大家可以作为参考用于自己的项目中。 25 | 26 | #####i. `GankApi`:这个类用来定义相关的`http`接口,这是符合retrofit规范的定义形式,每一个api返回的为`Observable`格式结果,方便`RxJava`进行进一步处理。 27 | @GET("/data/福利/{page}") Observable getMeizhiList(@Path("page") int page); 28 | @GET("/data/休息视频/{page}") Observable getGankVideoList(@Path("page") int page); 29 | #####ii. `DrakeetRetrofit`:这个类用来对`Retrofit`进行相关配置并生成`GankApi`实例`gankApi` 30 | OkHttpClient client = new OkHttpClient(); 31 | RestAdapter.Builder builder = new RestAdapter.Builder(); 32 | builder.setClient(new OkClient(client)) 33 | .setLogLevel(RestAdapter.LogLevel.FULL) 34 | .setEndpoint("http://gank.io/api") 35 | .setConverter(new GsonConverter(gson)); 36 | RestAdapter gankRestAdapter = builder.build(); 37 | GankApi gankApi = gankRestAdapter.create(GankApi.class); 38 | 39 | public GankApi getGankApi() { 40 | return gankApi; 41 | } 42 | #####iii. `DrakeetFactory`: 这个类用来对外生成单例`GankApi`实例,为确保`GankApi`实例只生成一次。 43 | public static GankApi getGankApi() { 44 | synchronized (monitor) { 45 | if (sGankApi == null) { 46 | sGankApi = new DrakeetRetrofit().getGankApi(); 47 | } 48 | return sGankApi; 49 | } 50 | } 51 | 52 | 所以,在实际应用场景中,比如我们想要发起一个http请求来获取`福利`数据,那么我们可以采用以下方式: 53 | 54 | GankApi gankApi = DrakeetFactory.getGankApi(); 55 | Observable meizhiList = gankApi. getMeizhiList(10); 56 | 57 | 58 | ![首页.png](http://upload-images.jianshu.io/upload_images/281665-2129d871aff9a884.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 59 | 60 | ###3. 首页的RxJava的实现 61 | 既然我们已经把网络框架搭建好了,那么可以开始从服务器获取数据并显示了。我们首先看首页的数据。下面,我来对首页数据进行分析,一步步推出所需要的RxJava表达式。 62 | 63 | 上面已经介绍过,每一个card里有两部分数据:`妹纸图片`(红色方框)和`描述文本`(绿色方框)。 64 | 65 | - `妹纸图片`数据来自于`"/data/福利/{page}"`这个api,该api会返回妹纸图片的url; 66 | - `描述文本`来自于`"/data/休息视频/{page}"`这个api,该api会返回休息视频及相关描述信息,card里会把描述信息显示出来; 67 | - 两个api均可以携带`page`字段,即一次请求可以获得多个数据。如我们在`"/data/福利/{page}"`里设置`page=10`,那么我们一次请求可以得到10条`福利`数据,即`10张妹纸图片url`; 68 | - 由于我们一次可以获得多张妹纸图片url和多个视频信息,那我们就需要把`二者进行合并`,即`单拎出来一张妹纸图片和一个视频信息组装成一个card`。然后按这种方式生成其他的card。 69 | 70 | 小结一下,根据以上描述,假如我们把两个api的page都设置为`10`,那么两个请求同时发出去后,我们能得到`10张妹纸图片url`(如`http://img.com/1.png`, `http://img.com/2.png`, ...)和`10个视频信息`(如`舌尖上的中国`, `星际穿越`, ...),然后我们将二者组装成`10个card所需要的数据`,放入每个card里显示即可。 71 | 72 | 好,终于可以开始动手写代码了。上面的分析看似复杂,然后只要你学会了如何分析,很快就能写出对应的RxJava代码。下面我结合RxJava的`数据流思想`和`具体操作符`来介绍实现代码。 73 | 74 | #####i. 在网络请求数据之前,我们要创建几个数据entry对象来将获取回来的json字符串转化为object 75 | public class Meizhi { 76 | public String url; 77 | public Date publishDate; 78 | } //这是一个Meizhi对象,存储妹纸图片的url,图片描述信息和创建日期 79 | 80 | public class Video { 81 | public String desc; 82 | public Date publishDate; 83 | } //这是一个视频对象,存储视频描述信息和创建日期 84 | 85 | public class MeizhiList { 86 | public List meizhiList; 87 | } //由于我们一次请求能获取到10个(根据`page`设置),所以我们用MeizhiList来存储结果 88 | 89 | public class VideoList { 90 | public List