├── LICENSE
├── README.md
└── translations
├── Chinese
└── README.cn.md
├── French
└── README.fr.md
├── Japanese
└── README.ja.md
├── Korean
└── README.ko.md
├── Portuguese
└── README.pt.md
├── Russian
└── README.ru.md
├── Spanish
└── README.es.md
├── Turkish
└── README.tr.md
└── Vietnamese
└── README.vi.md
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
2 |
3 | Using Creative Commons Public Licenses
4 |
5 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
6 |
7 | Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.
8 |
9 | Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.
10 |
11 | Creative Commons Attribution 4.0 International Public License
12 |
13 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
14 |
15 | Section 1 – Definitions.
16 |
17 | Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
18 | Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
19 | Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
20 | Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
21 | Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
22 | Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
23 | Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
24 | Licensor means the individual(s) or entity(ies) granting rights under this Public License.
25 | Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
26 | Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
27 | You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
28 |
29 | Section 2 – Scope.
30 |
31 | License grant.
32 | Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
33 | reproduce and Share the Licensed Material, in whole or in part; and
34 | produce, reproduce, and Share Adapted Material.
35 | Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
36 | Term. The term of this Public License is specified in Section 6(a).
37 | Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
38 | Downstream recipients.
39 | Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
40 | No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
41 | No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
42 |
43 | Other rights.
44 | Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
45 | Patent and trademark rights are not licensed under this Public License.
46 | To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
47 |
48 | Section 3 – License Conditions.
49 |
50 | Your exercise of the Licensed Rights is expressly made subject to the following conditions.
51 |
52 | Attribution.
53 |
54 | If You Share the Licensed Material (including in modified form), You must:
55 | retain the following if it is supplied by the Licensor with the Licensed Material:
56 | identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
57 | a copyright notice;
58 | a notice that refers to this Public License;
59 | a notice that refers to the disclaimer of warranties;
60 | a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
61 | indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
62 | indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
63 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
64 | If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
65 | If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.
66 |
67 | Section 4 – Sui Generis Database Rights.
68 |
69 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
70 |
71 | for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
72 | if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
73 | You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
74 |
75 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
76 |
77 | Section 5 – Disclaimer of Warranties and Limitation of Liability.
78 |
79 | Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
80 | To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
81 |
82 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
83 |
84 | Section 6 – Term and Termination.
85 |
86 | This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
87 |
88 | Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
89 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
90 | upon express reinstatement by the Licensor.
91 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
92 | For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
93 | Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
94 |
95 | Section 7 – Other Terms and Conditions.
96 |
97 | The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
98 | Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
99 |
100 | Section 8 – Interpretation.
101 |
102 | For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
103 | To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
104 | No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
105 | Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
106 |
107 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
108 |
109 | Creative Commons may be contacted at creativecommons.org.
--------------------------------------------------------------------------------
/translations/Chinese/README.cn.md:
--------------------------------------------------------------------------------
1 | # Android 开发最佳实践
2 |
3 | 从[Futurice](http://www.futurice.com)公司Android开发者中学到的经验。
4 | 遵循以下准则,避免重复发明轮子。若你对开发iOS或Windows Phone 有兴趣,
5 | 请看[**iOS Good Practices**](https://github.com/futurice/ios-good-practices) 和 [**Windows client Good Practices**](https://github.com/futurice/win-client-dev-good-practices) 这两篇文章。
6 |
7 | ## 摘要
8 |
9 | * 使用 Gradle 和它推荐的工程结构
10 | * 把密码和敏感数据放在gradle.properties
11 | * 不要自己写 HTTP 客户端,使用Volley或OkHttp库
12 | * 使用Jackson库解析JSON数据
13 | * 避免使用Guava同时使用一些类库来避免*65k method limit*(一个Android程序中最多能执行65536个方法)
14 | * 使用 Fragments来呈现UI视图
15 | * 使用 Activities 只是为了管理 Fragments
16 | * Layout 布局是 XMLs代码,组织好它们
17 | * 在layoutout XMLs布局时,使用styles文件来避免使用重复的属性
18 | * 使用多个style文件来避免单一的一个大style文件
19 | * 保持你的colors.xml 简短DRY(不要重复自己),只是定义调色板
20 | * 总是使用dimens.xml DRY(不要重复自己),定义通用常数
21 | * 不要做一个深层次的ViewGroup
22 | * 在使用WebViews时避免在客户端做处理,当心内存泄露
23 | * 使用Robolectric单元测试,Robotium 做UI测试
24 | * 使用Genymotion 作为你的模拟器
25 | * 总是使用ProGuard 和 DexGuard混淆来项目
26 |
27 | ### Android SDK
28 |
29 | 将你的[Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools)放在你的home目录或其他应用程序无关的位置。
30 | 当安装有些包含SDK的IDE的时候,可能会将SDK放在IDE同一目录下,当你需要升级(或重新安装)IDE或更换的IDE时,会非常麻烦。
31 | 此外,如果你的IDE是在普通用户下运行,而不是在root下运行,还要避免把SDK放到一下需要sudo权限的系统级别目录下。
32 |
33 | ### 构建系统
34 |
35 | 你的默认编译环境应该是[Gradle](http://tools.android.com/tech-docs/new-build-system).
36 | Ant 有很多限制,也很冗余。使用Gradle,完成以下工作很方便:
37 |
38 | - 构建APP不同版本的变种
39 | - 制作简单类似脚本的任务
40 | - 管理和下载依赖
41 | - 自定义秘钥
42 | - 更多
43 |
44 | 同时,Android Gradle插件作为新标准的构建系统正在被Google积极的开发。
45 |
46 | ### 工程结构
47 |
48 | 有两种流行的结构:老的Ant & Eclipse ADT 工程结构,和新的Gradle & Android Studio 工程结构,
49 | 你应该选择新的工程结构,如果你的工程还在使用老的结构,考虑放弃吧,将工程移植到新的结构。
50 |
51 |
52 | 老的结构:
53 |
54 | ```
55 | old-structure
56 | ├─ assets
57 | ├─ libs
58 | ├─ res
59 | ├─ src
60 | │ └─ com/futurice/project
61 | ├─ AndroidManifest.xml
62 | ├─ build.gradle
63 | ├─ project.properties
64 | └─ proguard-rules.pro
65 | ```
66 |
67 | 新的结构
68 |
69 | ```
70 | new-structure
71 | ├─ library-foobar
72 | ├─ app
73 | │ ├─ libs
74 | │ ├─ src
75 | │ │ ├─ androidTest
76 | │ │ │ └─ java
77 | │ │ │ └─ com/futurice/project
78 | │ │ └─ main
79 | │ │ ├─ java
80 | │ │ │ └─ com/futurice/project
81 | │ │ ├─ res
82 | │ │ └─ AndroidManifest.xml
83 | │ ├─ build.gradle
84 | │ └─ proguard-rules.pro
85 | ├─ build.gradle
86 | └─ settings.gradle
87 | ```
88 |
89 | 主要的区别在于,新的结构明确的分开了'source sets' (`main`,`androidTest`),这是Gradle的一个理念。
90 | 通过这个你可以做到,例如,添加源组‘paid’和‘free’在src中,让你的应用程序具有付费和免费的两种模式的源代码。
91 |
92 | 你的项目引用第三方项目库时(例如,library-foobar),拥有一个顶级包名`app`从第三方库项目区分你的应用程序是非常有用的。
93 | 然后`settings.gradle`不断引用这些库项目,其中`app/build.gradle`可以引用。
94 |
95 | ### Gradle 配置
96 |
97 | **常用结构** 参考[Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)
98 |
99 |
100 | **小任务** 除了(shell, Python, Perl, etc)这些脚本语言,你也可以使用Gradle 制作任务。
101 | 更多信息请参考[Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF)。
102 |
103 |
104 | **密码** 在做版本release时你app的 `build.gradle`你需要定义 `signingConfigs`.此时你应该避免以下内容:
105 |
106 |
107 | _不要做这个_ . 这会出现在版本控制中。
108 |
109 | ```groovy
110 | signingConfigs {
111 | release {
112 | storeFile file("myapp.keystore")
113 | storePassword "password123"
114 | keyAlias "thekey"
115 | keyPassword "password789"
116 | }
117 | }
118 | ```
119 |
120 | 而是,建立一个不加入版本控制系统的`gradle.properties`文件。
121 |
122 | ```
123 | KEYSTORE_PASSWORD=password123
124 | KEY_PASSWORD=password789
125 | ```
126 |
127 |
128 | 那个文件是gradle自动引入的,你可以在`buld.gradle`文件中使用,例如:
129 |
130 | ```groovy
131 | signingConfigs {
132 | release {
133 | try {
134 | storeFile file("myapp.keystore")
135 | storePassword KEYSTORE_PASSWORD
136 | keyAlias "thekey"
137 | keyPassword KEY_PASSWORD
138 | }
139 | catch (ex) {
140 | throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
141 | }
142 | }
143 | }
144 | ```
145 |
146 |
147 | **使用 Maven 依赖方案代替使用导入jar包方案** 如果在你的项目中你明确使用某些
148 | jar文件,那么它们可能成为固定的版本,如`2.1.1`.下载jar包更新他们是很繁琐的,
149 | 这个问题Maven很好的解决了,这在Android Gradle构建中也是推荐的方法。你可
150 | 以指定版本的一个范围,如`2.1.+`,然后Maven会自动升级到制定的最新版本,例如:
151 |
152 | ```groovy
153 | dependencies {
154 | implementation 'com.netflix.rxjava:rxjava-core:0.19.+'
155 | implementation 'com.netflix.rxjava:rxjava-android:0.19.+'
156 | implementation 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
157 | implementation 'com.fasterxml.jackson.core:jackson-core:2.4.+'
158 | implementation 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
159 | implementation 'com.squareup.okhttp:okhttp:2.0.+'
160 | implementation 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
161 | }
162 | ```
163 |
164 | ### IDEs and text editors
165 |
166 | ### IDE集成开发环境和文本编辑器
167 |
168 |
169 | **无论使用什么编辑器,一定要构建一个良好的工程结构。** 编辑器每个人都有自己的
170 | 选择,让你的编辑器根据工程结构和构建系统运作,那是你自己的责任。
171 |
172 | 当下首推[Android Studio](https://developer.android.com/sdk/installing/studio.html),因为他是由谷歌开发,很好地支持Gradle,包含很多有用的检测和分析工具,默认使用最新的工程结构,它就是为Android开发定制的。
173 |
174 | 你也可以使用纯文版编辑器如Vim,Sublime Text,或者Emacs。如果那样的话,你需要使用Gradle和`adb`命令行。
175 |
176 | 不再推荐使用Eclipse和ADT开发,因为[谷歌在2015年年末结束了对ADT的支持](https://android-developers.googleblog.com/2015/06/an-update-on-eclipse-android-developer.html),并呼吁开发者尽快迁移到Android Studio。
177 |
178 | 无论你使用何种开发工具,避免将你的编辑器配置文件(比如Android Studio的iml文件)加入到版本控制,因为这些文件通常包含与本地机器有关的配置,可能会影响你的同事。
179 |
180 | 最后,善待其他开发者,不要强制改变他们的开发工具和偏好。
181 |
182 | ### 类库
183 |
184 |
185 | **[Jackson](http://wiki.fasterxml.com/JacksonHome)** 是一个将java对象转换成JSON与JSON转化java类的类库。[Gson](https://code.google.com/p/google-gson/)
186 | 是解决这个问题的流行方案,然而我们发现Jackson更高效,因为它支持替代的方法处理JSON:流、内存树模型,和传统JSON-POJO数据绑定。不过,请记住,
187 | Jsonkson库比起GSON更大,所以根据你的情况选择,你可能选择GSON来避免APP 65k个方法的限制。其它选择: [Json-smart](https://code.google.com/p/json-smart/) and [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)
188 |
189 |
190 | **网络请求,缓存,图片** 执行请求后端服务器,有几种交互的解决方案,你应该考虑实现你自己的网络客户端。使用 [Volley](https://android.googlesource.com/platform/frameworks/volley)
191 | 或[Retrofit](http://square.github.io/retrofit/)。Volley 同时提供图片缓存类。如果你选择使用Retrofit,那么考虑使用[Picasso](http://square.github.io/picasso/)
192 | 来加载图片和缓存,同时使用[OkHttp](http://square.github.io/okhttp/)作为高效的网络请求。Retrofit,Picasso和OkHttp都是同一家公司开发(注:
193 | 是由[Square](https://github.com/square) 公司开发),所以它们能很好的在一起运行。[OkHttp 同样可以和Volley在一起使用 Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).
194 |
195 | **RxJava** 是函数式反应性的一个类库,换句话说,能处理异步的事件。
196 | 这是一个强大的和有前途的模式,同时也可能会造成混淆,因为它是如此的不同。
197 | 我们建议在使用这个库架构整个应用程序之前要谨慎考虑。
198 | 有一些项目是使用RxJava完成的,如果你需要帮助可以跟这些人取得联系:
199 | Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen.
200 | 我们也写了一些博客:
201 | [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android),
202 | [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754),
203 | [[4]](http://blog.futurice.com/android-development-has-its-own-swift).
204 |
205 |
206 | 如若你之前有使用过Rx的经历,开始从API响应应用它。
207 | 另外,从简单的UI事件处理开始运用,如单击事件或在搜索栏输入事件。
208 | 若对你的Rx技术有信心,同时想要将它应用到你的整体架构中,那么请在复杂的部分写好Javadocs文档。
209 | 请记住其他不熟悉RxJava的开发人员,可能会非常难理解整个项目。
210 | 尽你的的全力帮助他们理解你的代码和Rx。
211 |
212 | **[Retrolambda](https://github.com/evant/gradle-retrolambda)** 是一个在Android和预JDK8平台上的使用Lambda表达式语法的Java类库。
213 | 它有助于保持你代码的紧凑性和可读性,特别当你使用如RxJava函数风格编程时。
214 | 使用它时先安装JDK8,在Android Studio工程结构对话框中把它设置成为SDK路径,同时设置`JAVA8_HOME`和`JAVA7_HOME`环境变量,
215 | 然后在工程根目录下配置 build.gradle:
216 |
217 | ```groovy
218 | dependencies {
219 | classpath 'me.tatarka:gradle-retrolambda:2.4.+'
220 | }
221 | ```
222 |
223 | 同时在每个module 的build.gradle中添加
224 |
225 | ```groovy
226 | apply plugin: 'retrolambda'
227 |
228 | android {
229 | compileOptions {
230 | sourceCompatibility JavaVersion.VERSION_1_8
231 | targetCompatibility JavaVersion.VERSION_1_8
232 | }
233 |
234 | retrolambda {
235 | jdk System.getenv("JAVA8_HOME")
236 | oldJdk System.getenv("JAVA7_HOME")
237 | javaVersion JavaVersion.VERSION_1_7
238 | }
239 | ```
240 |
241 | Android Studio 提供Java8 lambdas表带是代码提示支持。如果你对lambdas不熟悉,只需参照以下开始学习吧:
242 |
243 | - 任何只包含一个接口的方法都是"lambda friendly"同时代码可以被折叠成更紧凑的语法
244 | - 如果对参数或类似有疑问,就写一个普通的匿名内部类,然后让Android Studio 为你生成一个lambda。
245 |
246 | **当心dex方法数限制,同时避免使用过多的类库** Android apps,当打包成一个dex文件时,有一个65535个应用方法强硬限制[[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/)。
247 | 当你突破65k限制之后你会看到一个致命错误。因此,使用一个正常范围的类库文件,同时使用[dex-method-counts](https://github.com/mihaip/dex-method-counts)
248 | 工具来决定哪些类库可以再65k限制之下使用,特别的避免使用Guava类库,因为它包含超过13k个方法。
249 |
250 | ### Activities and Fragments
251 |
252 | [Fragments](http://developer.android.com/guide/components/fragments.html)应该作为你实现UI界面默认选择。你可以重复使用Fragments用户接口来
253 | 组合成你的应用。我们强烈推荐使用Fragments而不是activity来呈现UI界面,理由如下:
254 |
255 | - **提供多窗格布局解决方案** Fragments 的引入主要将手机应用延伸到平板电脑,所以在平板电脑上你可能有A、B两个窗格,但是在手机应用上A、B可能分别充满
256 | 整个屏幕。如果你的应用在最初就使用了fragments,那么以后将你的应用适配到其他不同尺寸屏幕就会非常简单。
257 |
258 | - **屏幕间数据通信** 从一个Activity发送复杂数据(例如Java对象)到另外一个Activity,Android的API并没有提供合适的方法。不过使用Fragment,你可以使用
259 | 一个activity实例作为这个activity子fragments的通信通道。即使这样比Activity与Activity间的通信好,你也想考虑使用Event Bus架构,使用如
260 | [Otto](https://square.github.io/otto/) 或者 [greenrobot EventBus](https://github.com/greenrobot/EventBus)作为更简洁的实现。
261 | 如果你希望避免添加另外一个类库,RxJava同样可以实现一个Event Bus。
262 |
263 |
264 | - **Fragments 一般通用的不只有UI** 你可以有一个没有界面的fragment作为Activity提供后台工作。
265 | 进一步你可以使用这个特性来创建一个[fragment 包含改变其它fragment的逻辑](http://stackoverflow.com/questions/12363790/how-many-activities-vs-fragments/12528434#12528434)
266 | 而不是把这个逻辑放在activity中。
267 |
268 | - **甚至ActionBar 都可以使用内部fragment来管理** 你可以选择使用一个没有UI界面的fragment来专门管理ActionBar,或者你可以选择使用在每个Fragment中
269 | 添加它自己的action 来作为父Activity的ActionBar.[参考](http://www.grokkingandroid.com/adding-action-items-from-within-fragments/).
270 |
271 | 很不幸,我们不建议广泛的使用嵌套的[fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments),因为
272 | 有时会引起[matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/)。我们只有当它有意义(例如,在水平滑动的ViewPager在
273 | 像屏幕一样fragment中)或者他的确是一个明智的选择的时候才广泛的使用fragment。
274 |
275 | 在一个架构级别,你的APP应该有一个顶级的activity来包含绝大部分业务相关的fragment。你也可能还有一些辅助的activity ,这些辅助的activity与主activity
276 | 通信很简单限制在这两种方法
277 | [`Intent.setData()`](http://developer.android.com/reference/android/content/Intent.html#setData(android.net.Uri)) 或 [`Intent.setAction()`](http://developer.android.com/reference/android/content/Intent.html#setAction(java.lang.String))或类似的方法。
278 |
279 |
280 | ### Java 包结构
281 |
282 | Android 应用程序在架构上大致是Java中的[Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)结构。
283 | 在Android 中 Fragment和Activity通常上是控制器类(http://www.informit.com/articles/article.aspx?p=2126865).
284 | 换句话说,他们是用户接口的部分,同样也是Views视图的部分。
285 |
286 |
287 | 正是因为如此,才很难严格的将fragments (或者 activities) 严格的划分成 控制器controlloers还是视图 views。
288 | 最还是将它们放在自己单独的 `fragments` 包中。只要你遵循之前提到的建议,Activities 则可以放在顶级目录下。
289 | 如果你规划有2到3个以上的activity,那么还是同样新建一个`activities`包吧。
290 |
291 | 然而,这种架构可以看做是另一种形式的MVC,
292 | 包含要被解析API响应的JSON数据,来填充的POJO的`models`包中。
293 | 和一个`views`包来包含你的自定义视图、通知、导航视图,widgets等等。
294 | 适配器Adapter是在数据和视图之间。然而他们通常需要通过`getView()`方法来导出一些视图,
295 | 所以你可以将`adapters`包放在`views`包里面。
296 |
297 | 一些控制器角色的类是应用程序级别的,同时是接近系统的。
298 | 这些类放在`managers`包下面。
299 | 一些繁杂的数据处理类,比如说"DateUtils",放在`utils`包下面。
300 | 与后端交互负责网络处理类,放在`network`包下面。
301 |
302 |
303 | 总而言之,以最接近用户而不是最接近后端去安排他们。
304 |
305 | ```
306 | com.futurice.project
307 | ├─ network
308 | ├─ models
309 | ├─ managers
310 | ├─ utils
311 | ├─ fragments
312 | └─ views
313 | ├─ adapters
314 | ├─ actionbar
315 | ├─ widgets
316 | └─ notifications
317 | ```
318 |
319 |
320 | ### 资源文件 Resources
321 |
322 |
323 | - **命名** 遵循前缀表明类型的习惯,形如`type_foo_bar.xml`。例如:`fragment_contact_details.xml`,`view_primary_button.xml`,`activity_main.xml`.
324 |
325 | **组织布局文件** 如果你不确定如何排版一个布局文件,遵循一下规则可能会有帮助。
326 |
327 | - 每一个属性一行,缩进4个空格
328 | - `android:id` 总是作为第一个属性
329 | - `android:layout_****` 属性在上边
330 | - `style` 属性在底部
331 | - 关闭标签`/>`单独起一行,有助于调整和添加新的属性
332 | - 考虑使用[Designtime attributes 设计时布局属性](http://tools.android.com/tips/layout-designtime-attributes),Android Studio已经提供支持,而不是硬编码`android:text`
333 | (译者注:墙内也可以参考stormzhang的这篇博客[链接](http://stormzhang.com/devtools/2015/01/11/android-studio-tips1/))。
334 |
335 | ```xml
336 |
337 |
344 |
345 |
353 |
354 |
355 |
356 |
357 | ```
358 |
359 | 作为一个经验法则,`android:layout_****`属性应该在 layout XML 中定义,同时其它属性`android:****` 应放在 styler XML中。此规则也有例外,不过大体工作
360 | 的很好。这个思想整体是保持layout属性(positioning, margin, sizing) 和content属性在布局文件中,同时将所有的外观细节属性(colors, padding, font)放
361 | 在style文件中。
362 |
363 |
364 | 例外有以下这些:
365 |
366 | - `android:id` 明显应该在layout文件中
367 | - layout文件中`android:orientation`对于一个`LinearLayout`布局通常更有意义
368 | - `android:text` 由于是定义内容,应该放在layout文件中
369 | - 有时候将`android:layout_width` 和 `android:layout_height`属性放到一个style中作为一个通用的风格中更有意义,但是默认情况下这些应该放到layout文件中。
370 |
371 | **使用styles** 几乎每个项目都需要适当的使用style文件,因为对于一个视图来说有一个重复的外观是很常见的。
372 | 在应用中对于大多数文本内容,最起码你应该有一个通用的style文件,例如:
373 |
374 | ```xml
375 |
379 | ```
380 |
381 | 应用到TextView 中:
382 |
383 | ```xml
384 |
390 | ```
391 |
392 |
393 | 你或许需要为按钮控件做同样的事情,不要停止在那里。将一组相关的和重复`android:****`的属性放到一个通用的style中。
394 |
395 |
396 | **将一个大的style文件分割成多个文件** 你可以有多个`styles.xml` 文件。Android SDK支持其它文件,`styles`这个文件名称并没有作用,起作用的是在文件
397 | 里xml的`
291 | ```
292 |
293 | Appliqué aux TextViews:
294 |
295 | ```xml
296 |
302 | ```
303 |
304 | Vous aurez probablement besoin de faire la même chose pour les boutons, mais ne vous arretez pas là. Allez plus loin et mettez les groupes d'attributs qui se répètent dans un style commun.
305 |
306 | **Séparez les fichiers de style très gros en plusieurs petits fichiers de style.** Vous n'êtes pas contraints d'avoir qu'un seul fichier `styles.xml`. Le SDK Android supporte plusieurs fichiers de style, il n'y a rien de magique avec le nom `styles`, ce qui importe ce sont les tags XML `
316 | ```
317 |
318 | このスタイルはTextViewで下記の用に使う事ができる。
319 |
320 | ```xml
321 |
327 | ```
328 |
329 | 同じことをボタンにもする必要があるが、そこで終わりにせず、関連性のあるまたは繰り返されたグループを移動して、`android:****`を共通のStyleに書き出そう。
330 |
331 | **大きなStyle Fileを避け、複数に分けよう。**
332 | 1つの`styles.xml`だけを持つ事は止めた方が良い。styleファイルは`style_home.xml`、`style_item_details.xml`、`styles_forms.xml`と言ったように複数持つ事ができる。`res/values`の中のファイル名は任意である。
333 |
334 | **`color.xml`はカラーパレットである。**
335 | colors.xmlは色の名前で定義しよう。下記のように各ボタンによって定義するといったようなことはすべきじゃない。
336 |
337 | *下記は良くない例。*
338 |
339 | ```xml
340 |
341 | #FFFFFF
342 | #2A91BD
343 | #5F5F5F
344 | #939393
345 | #FFFFFF
346 | #FF9D2F
347 | ...
348 | #323232
349 | ```
350 |
351 | こういう書き方をしてしまうと基本色を変更する場合などに対応しづらい。"button"や"comment"といった内容はbutton styleで定義すればよく、`colors.xml`の中に定義すべきではない。
352 |
353 | `colors.xml`は下記のように定義しよう。
354 |
355 | ```xml
356 |
357 |
358 |
359 | #FFFFFF
360 | #DBDBDB
361 | #939393
362 | #5F5F5F
363 | #323232
364 |
365 |
366 | #27D34D
367 | #2A91BD
368 | #FF9D2F
369 | #FF432F
370 |
371 |
372 | ```
373 |
374 | nameは色の名前でなく"brand_primary", "brand_secondary", "brand_negative"などとしても良い。そうする事で色の変更がしやすくなり、またどれだけの色が使われているかがわかりやすい。通常、きれいなUIの為には使用する色を減らす事も重要だ。
375 |
376 | **dimens.xmlもcolors.xmlのように扱おう。**
377 | 典型的なスペースやフォントサイズをcolors.xmlのパレットのように定義しよう。下記は良い例である。
378 |
379 | ```xml
380 |
381 |
382 |
383 | 22sp
384 | 18sp
385 | 15sp
386 | 12sp
387 |
388 |
389 | 40dp
390 | 24dp
391 | 14dp
392 | 10dp
393 | 4dp
394 |
395 |
396 | 60dp
397 | 40dp
398 | 32dp
399 |
400 |
401 | ```
402 |
403 | marginやpaddingをハードコードするのではなく、`spacing_****`を使用するようにしよう。そうする事で簡単に全体に統一感を持たす事ができ、また整理も簡単にできる。
404 |
405 | **Viewの深いネストは止めよう。**
406 | 下記のようにLinearLayoutを組み合わせてViewを作ろうとすることがある。
407 | そうするとLayout xmlは下記のようになる。
408 |
409 | ```xml
410 |
415 |
416 |
419 |
420 |
423 |
424 |
427 |
428 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 | ```
441 |
442 | もし、一つのLayout ファイルに書いていなくてもJava側でinflateした際に同じ状況になる事もあり得る。
443 |
444 | これはいくつかの問題起こす。まずはきっとあなたも経験しただろう、UIの煩雑さによるパフォーマンス低下の問題である。他にも深刻な[StackOverFlow](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views)を起こす可能性もある。
445 |
446 | 以上の理由から、Viewの階層はなるべくフラットにするべきである。そのために[RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html)の使い方、[Layoutの最適化](http://developer.android.com/training/improving-layouts/optimizing-layout.html)の方法、[\タグ](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts)の使い方を知っておこう。
447 |
448 | **WebViewの参照問題に気をつけよう。**
449 | 例えばNewsの記事などのweb pageを表示する必要がある場合、クライアントサイドでHTMLを整形する事は止めた方が良い。HTMLはバックグラウンドプログラマに用意してもらおう。また[WebViewはActivityの参照を持つときにメモリリークしうる](http://stackoverflow.com/questions/3130654/memory-leak-in-webview)。Activityの代わりにApplicationContextを使用しよう。単純なテキストやボタンを表示するのにTextViewやButtonではなくWebViewを使用する事も避けた方がいい。
450 |
451 |
452 | ### テストフレームワーク
453 |
454 | Android SDKのテストフレームワークは特にUIテストにおいてまだまだ未熟なところがある。
455 | Android Gradleに、あなたがAndroidのJUnitのヘルパーを使って書いたJUnitのテストを走らせる[connectedAndroidTest](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing)がある。これはdeviceもしくはemulatorをつなぐ必要がある。次のテストガイドを見ておこう。[\[1\]](http://developer.android.com/tools/testing/testing_android.html) [\[2\]] (http://developer.android.com/tools/testing/activity_test.html)
456 |
457 | **viewを使わないUnitテストには[Robolectric](http://robolectric.org/)を使おう。**
458 | このテストフレームワークはデバイスにつなぐ必要がないため開発効率があがる。UIのテストには向いていないがモデルとViewモデルのテストに適している。
459 |
460 | **[Robotium](https://code.google.com/p/robotium/)は簡単にUIテストを作る事ができる。**
461 | このテストフレームワークにはViewの取得、解析する為のヘルパーメソッド、スクリーンをコントロールする為のヘルパーメソッドが多く用意されている。テストケースも下記のようにシンプルに書く事ができる。
462 |
463 | ```java
464 | solo.sendKey(Solo.MENU);
465 | solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
466 | solo.clickOnText("Preferences");
467 | solo.clickOnText("Edit File Extensions");
468 | Assert.assertTrue(solo.searchText("rtf"));
469 | ```
470 |
471 | ### Emulator
472 |
473 | Androidアプリを専門で開発していくなら[Genymotion emulator](http://www.genymotion.com/)のライセンスは買っておいた方が良い。Genymotionは通常のAVD Emulatorよりも早い。またアプリのデモ、ネットワーク接続品質のエミュレート、GPS、などなどを行う為のツールがそろっている。
474 | テストはたくさんの端末で行わなければならないが、実際にたくさんの端末を買うよりはGenymotionのライセンスを買う方がコスパが良い。
475 |
476 | 注: GenymotionはGoogle Play StoreやMapなどがインストールされていない。またSamsungの特定のAPIをテストしたい場合は、実際のSamsungの端末を使う必要がある。
477 |
478 | ### Proguardの設定
479 |
480 | [ProGuard](http://proguard.sourceforge.net/)はAndroid Projectでコードを圧縮、難読化するために使われる。
481 |
482 | Proguardを使用するか否かはプロジェクトの設定に依る。通常リリースapkをビルドする際にProguardを使う場合gradleを下記のように設定する。
483 |
484 | ```groovy
485 | buildTypes {
486 | debug {
487 | runProguard false
488 | }
489 | release {
490 | signingConfig signingConfigs.release
491 | runProguard true
492 | proguardFiles 'proguard-rules.pro'
493 | }
494 | }
495 | ```
496 |
497 | どのコードを保存し、どのコードを捨て難読化するかをを明確に示さなければならない。デフォルトの設定では`SDK_HOME/tools/proguard/proguard-android.txt`を使用する。また`my-project/app/proguard-rules.pro`に定義する事でデフォルトのものに追加することができる。
498 |
499 | ProGuard関連のよくある問題でビルドが成功したにもかかわらず、アプリの起動で`ClassNotFoundException`や`NoSuchFieldException`などのExceptionを発生してアプリがクラッシュすることがある。これは以下の二つのどちらかを意味する。
500 |
501 | 1. ProGuardが必要なクラス、enum、関数、フィールド、アノテーションを削除してしまった。
502 | 2. リフレクションなどを使っており難読化によってリネームされたクラスへの参照ができない。
503 |
504 | もしあるオブジェクトが削除されている疑いがあるなら`app/build/outputs/proguard/release/usage.txt`を確認しよう。オブジェクトの難読化結果を見るなら`app/build/outputs/proguard/release/mapping.txt`を確認しよう。
505 |
506 | 必要なクラスや関数の削除を防ぐには`keep`オプションをproguard configに追加しよう。
507 | ```
508 | -keep class com.futurice.project.MyClass { *; }
509 | ```
510 |
511 | 難読化を防ぐには`keepnames`を使う。
512 | ```
513 | -keepnames class com.futurice.project.MyClass { *; }
514 | ```
515 |
516 | **Tip**
517 | リリースするたびに`mapping.txt`を保存しておこう。ユーザがバグを踏み、難読化されたスタックトレースを送ってきた際にデバッグする事ができる。
518 |
519 | **DexGuard**
520 | さらに最適化され、さらに難読化されたものを考えるならDexGuardの採用を考えよう。DexGuardはProGuardを作った同じチームが開発している商用のものである。さらにDexGuardなら簡単にDexファイルを分割し65k制限を解決する。
521 |
522 | ### Thanks to
523 |
524 | Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and other Futurice developers for sharing their knowledge on Android development.
525 |
526 | ### License
527 |
528 | [Futurice Oy](www.futurice.com)
529 | Creative Commons Attribution 4.0 International (CC BY 4.0)
530 |
531 |
532 | Translation
533 | ===========
534 |
535 | Translated to Japanese (`ja`) by **Shinnosuke Kugimiya, Aska Kadowaki**.
536 |
537 | Original content by [Futurice Oy](http://www.futurice.com).
538 |
539 |
--------------------------------------------------------------------------------
/translations/Korean/README.ko.md:
--------------------------------------------------------------------------------
1 | # Android 개발 모범 사례
2 |
3 | 다음은 [Futurice](http://www.futurice.com)의 Android 개발자들로부터 학습한 내용들이다. 이 가이드를 따라가면서 이미 했던 작업을 되풀이(Reinventing the wheel)하지 않도록 하자. iOS나 Windows Phone 개발에도 관심이 있다면, [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) 혹은 [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices) 문서들도 확인해보자.
4 |
5 | [](https://android-arsenal.com/details/1/1091)
6 |
7 | ## 요약
8 |
9 | #### Gradle을 사용하자. 이는 권장되는 프로젝트 구조이다.
10 | #### gradle.properties에 비밀번호나 민감한 데이터들을 넣어두자.
11 | #### HTTP 클라이언트를 직접 작성하지 말고, Volley나 OkHttp 라이브러리들을 사용하자.
12 | #### JSON 데이터를 파싱하는 데에는 Jackson 라이브러리를 사용하자.
13 | #### 65,000 메소드 수 제한을 방지하기 위해 Guava는 피하고 몇 가지의 라이브러리들만을 사용하자.
14 | #### UI 화면을 표현하는 데에 Fragment들을 사용하자.
15 | #### Fragment들을 관리하는 것은 Activity들이 맡도록 하자.
16 | #### 레이아웃 XML들 또한 코드이다. 그 것들을 잘 관리하자.
17 | #### 레이아웃 XML에서 중복된 속성들을 피하기 위해 style을 사용하자.
18 | #### 하나의 style이 방대해지는 것을 피하기 위해 여러가지 style 파일들을 사용하자.
19 | #### colors.xml을 짧게, 중복 없이 유지하고, 팔렛트처럼 정의해두자.
20 | #### dimens.xml 또한 중복 없이, 일반 상수로 정의하자.
21 | #### ViewGroup에 계층을 깊게 형성하지 않도록 하자.
22 | #### WebView에 클라이언트 측 프로세싱을 피하고, 여러 누수들에 유의하자.
23 | #### 유닛 테스트에는 Robolectric를 사용하고, UI 테스트에는 Robotium을 사용하자.
24 | #### 에뮬레이터로는 Genymotion를 사용하자.
25 | #### 항상 ProGuard 혹은 DexGuard를 사용하자.
26 |
27 |
28 | ----------
29 |
30 | ### Android SDK
31 |
32 | [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools)를 홈 디렉토리나 다른 애플리케이션에 독립적인 위치에 두자. 몇몇 IDE들은 설치시에 SDK를 해당 IDE와 같은 경로에 포함시키는데, 이는 IDE를 업그레이드(혹은 재설치)하거나 IDE가 변경될 때 불편하다. 또한 IDE가 root 아래에 있지 않고 user 아래에서 동작할 경우, SDK를 sudo 권한을 요구하는 시스템 레벨의 디렉토리에 두지 않도록 하자.
33 |
34 | ### 빌드 시스템
35 |
36 | 기본 옵션은 [Gradle](http://tools.android.com/tech-docs/new-build-system)이다. Ant는 상당히 제한적이고 내용이 장황하다. Gradle을 사용하면, 다음 항목들이 간단해진다.
37 |
38 | - 앱의 각기 다른 Flavor들과 Varient들을 빌드할 수 있다.
39 | - Task들을 간단한 스크립트처럼 만들 수 있다.
40 | - 여러 Dependency들을 관리하고 다운로드할 수 있다.
41 | - Keystore들을 커스터마이즈할 수 있다.
42 | - 기타 등등
43 |
44 | Android의 Gradle 플러그인은 새로운 표준 빌드 시스템으로서 구글에 의해 활발하게 개발되고 있다.
45 |
46 | ### 프로젝트 구조
47 |
48 | 두 가지 많이 쓰이는 옵션들이 있다: 낡은 Ant & Eclipse ADT 프로젝트 구조, 새로운 Gradle & Android Studio 프로젝트 구조가 있는데, 새로운 프로젝트 구조를 선택하자. 만약 낡은 구조를 사용하고 있다면, 레거시로 판단하고 새로운 구조로 포팅하는 작업을 시작하자.
49 |
50 | Old structure:
51 |
52 | ```
53 | old-structure
54 | ├─ assets
55 | ├─ libs
56 | ├─ res
57 | ├─ src
58 | │ └─ com/futurice/project
59 | ├─ AndroidManifest.xml
60 | ├─ build.gradle
61 | ├─ project.properties
62 | └─ proguard-rules.pro
63 | ```
64 |
65 | New structure:
66 |
67 | ```
68 | new-structure
69 | ├─ library-foobar
70 | ├─ app
71 | │ ├─ libs
72 | │ ├─ src
73 | │ │ ├─ androidTest
74 | │ │ │ └─ java
75 | │ │ │ └─ com/futurice/project
76 | │ │ └─ main
77 | │ │ ├─ java
78 | │ │ │ └─ com/futurice/project
79 | │ │ ├─ res
80 | │ │ └─ AndroidManifest.xml
81 | │ ├─ build.gradle
82 | │ └─ proguard-rules.pro
83 | ├─ build.gradle
84 | └─ settings.gradle
85 | ```
86 |
87 | 주된 차이점은 Gradle에서 온 개념인데, 새로운 구조가 'source sets' (`main`, `androidTest`)를 명시적으로 분리시켜둔다는 것이다. 예를 들어 `src`에 paid와 free라는 각기 다른 Flavor에 해당하는 소스코드를 갖는 'paid'라는 소스 셋과 'free'라는 소스 셋을 추가할 수 있다.
88 |
89 | 최상위 레벨 `app`을 갖는 것은 앱과 앱에서 참조된 다른 라이브러리 프로젝트들(e.g., `library-foobar`)을 구별하는 데에 유용하다. `settings.gradle`은 `app/build.gradle`에서 참조할 수 있는 이러한 라이브러리 프로젝트들을 보관한다.
90 |
91 | ### Gradle 설정
92 |
93 | **일반적인 구조.** [Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)를 확인하자.
94 |
95 | **작은 Task들.** 스크립트들(shell, Python, Perl, etc) 대신, Gradle의 Task들을 만들 수 있다. [Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF)에서 더 자세한 내용을 확인하자.
96 |
97 | **비밀번호** 앱의 `build.gradle`에 릴리즈 빌드를 위한 `signingConfigs` 정의가 필요할 것이다. 다음은 피하자.
98 |
99 | _아래 방법처럼 작업하지 않도록 한다_. 이는 버전 관리 시스템에서 나타날 것이다.
100 |
101 | ```groovy
102 | signingConfigs {
103 | release {
104 | storeFile file("myapp.keystore")
105 | storePassword "password123"
106 | keyAlias "thekey"
107 | keyPassword "password789"
108 | }
109 | }
110 | ```
111 |
112 | 대신, `gradle.properties` 파일을 만들자. 이는 버전 관리 시스템에 추가되어선 _안된다_:
113 |
114 | ```
115 | KEYSTORE_PASSWORD=password123
116 | KEY_PASSWORD=password789
117 | ```
118 |
119 | 위 파일은 gradle에 자동으로 임포트되어, `build.gradle`에 이렇게 사용할 수 있다:
120 |
121 | ```groovy
122 | signingConfigs {
123 | release {
124 | try {
125 | storeFile file("myapp.keystore")
126 | storePassword KEYSTORE_PASSWORD
127 | keyAlias "thekey"
128 | keyPassword KEY_PASSWORD
129 | }
130 | catch (ex) {
131 | throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
132 | }
133 | }
134 | }
135 | ```
136 |
137 | **jar 파일 임포트 대신 Maven을 선호하자.** 프로젝트에 jar 파일을 명시적으로 포함시킬 경우, 이들은 `2.1.1`처럼 특정하게 고정된 버전이 된다. jar를 다운로드하고, 업데이트하는 것은 귀찮은 일이다. 그러나 Maven은 이 문제를 적절하게 해결해줄 것이고, 또한 이는 Android Gradle 빌드에서 장려되는 방식이다. 예를 들자면 이렇다:
138 |
139 | ```groovy
140 | dependencies {
141 | implementation 'com.squareup.okhttp:okhttp:2.2.0'
142 | implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
143 | }
144 | ```
145 |
146 | **Maven의 동적 의존성 해결을 피하라**
147 | `2.1.+`과 같이 동적으로 버전을 정하는 방식은 불안정하고, 빌드 사이에 미묘하고 이해하기 어려운 차이를 초래할 수 있어 피하도록 하자. `2.1.1`처럼 정적으로 고정된 버전을 사용하는 것이 보다 안정적이고, 예측 가능하고, 반복적인 개발 환경을 구성하는 데에 도움이 될 것이다.
148 |
149 | ### IDE와 텍스트 에디터
150 |
151 | **프로젝트 구조를 다루는 데에 용이한 에디터라면 무엇이든 사용해도 좋다.** 에디터는 개인적인 선택이고, 그 에디터가 프로젝트 구조와 프로젝트 빌드 시스템에 따라 기능하도록 하는 것은 개발자의 몫이다.
152 |
153 | 현재 가장 추천하는 IDE는 [Android Studio](https://developer.android.com/sdk/installing/studio.html)이다. Google이 개발했고, Gradle에 가장 밀접하며, 기본적으로 새로운 프로젝트 구조를 사용하는데다가 안정화 단계에 들어가 Android 개발에 잘 맞추어져 있기 때문이다.
154 |
155 | 원한다면 [Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt)를 사용해도 좋지만, 빌드하는 데에 낡은 프로젝트 구조와 Ant를 사용하기 때문에 이에 대한 설정이 필요하다. Vim, Sublime Text, Emacs같은 플레인 텍스트 에디터를 사용할 수도 있다. 이 경우에는 Gradle과 `adb`를 커맨드라인에서 사용해야 한다. Eclipse의 Gradle 사용이 제대로 작동하지 않는다면, 커맨드라인으로 빌드하거나 Android Studio로 옮기자. ADT 플러그인이 deprecate되었기 때문에, 이 것이 가장 좋은 옵션일 것이다.
156 |
157 | 무엇을 사용하든, 애플리케이션 빌드의 공식적인 방법인 Gradle과 새로운 프로젝트 구조를 따르고, 특정 에디터를 따르는 설정 파일을 버전 관리 시스템에 추가하는 것을 피하는 것만 명심하자. 예를 들면, Ant의 `build.xml` 파일들은 추가하지 않도록 한다. 특히 Ant의 빌드 설정을 변경하고 있다면 `build.gradle`을 최신의 상태로 기능하도록 하는 것을 잊지말자. 또한 다른 개발자들에게 친절해지자. 그들의 설정을 바꾸도록 강요하지 않아야한다.
158 |
159 | ### 라이브러리
160 |
161 | **[Jackson](http://wiki.fasterxml.com/JacksonHome)**은 Object를 JSON으로, 혹은 그 반대로 변환해주는 Java 라이브러리이다. [Gson](https://code.google.com/p/google-gson/)이 이 문제를 해결하는 데에 많이 쓰이긴 하지만, 스트리밍, 인메모리 트리 모델, 전통적인 JSON-POJO 데이터 바인딩과 같은 여러 대안들을 지원하는 Jackson이 더 고성능일 것이다. 하지만 명심하자. Jackson이 GSON보다 더 큰 라이브러리이기 때문에, 65,000 메소드 수 제한에 부딪힌 경우라면 GSON을 사용하는 것이 나을 수도 있다. 다른 대안으로는 [Json-smart](https://code.google.com/p/json-smart/)과 [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)이 있다.
162 |
163 | **네트워킹, 캐싱, 이미지.** 백엔드 서버로의 요청 처리에 대해 클라이언트를 구현하고 처리하는 두 가지 검증된 해결책이 있다. [Volley](https://android.googlesource.com/platform/frameworks/volley) 혹은 [Retrofit](http://square.github.io/retrofit/)을 사용하자. Volley는 이미지를 불러오고 캐싱하는 도우미를 제공한다. Retrofit을 선택한다면, 이미지 로딩과 캐싱에는 [Picasso](http://square.github.io/picasso/)를, 효율적인 HTTP 요청에는 [OkHttp](http://square.github.io/okhttp/)를 고려해보자. 이 모든 세가지의 라이브러리들은 같은 회사에서 개발되어 서로 상호보완이 매우 용이하다. [OkHttp can also be used in connection with Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).
164 |
165 | **RxJava** 비동기 이벤트를 처리하는 Reactive Programming을 위한 라이브러리이다. 이는 매우 강력하고 유망한 패러다임으로, 너무 다른 점이 많아 혼란스러울 수 있다. 모든 애플리케이션에서 아키텍트들에게 이 라이브러리를 쓰기 전 주의할 것을 추천한다. RxJava를 이용한 몇 가지 프로젝트가 있는데, 필요하다면 이 사람들에게서 도움을 구하자: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. 작성된 블로그 포스트도 있다: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).
166 |
167 | Rx에 대한 경험이 없다면, API 응답 처리에만 적용해보자. 다른 방법으로는 클릭 이벤트나 검색 타이핑 이벤트와 같은 간단한 UI 이벤트 처리에 적용해볼 수도 있다. Rx 기술에 자신감이 생겨 모든 설계에 적용하고 싶다면, 모든 까다로운 부분들에 Javadocs를 작성하자. RxJava에 익숙하지 않은 다른 프로그래머가 프로젝트를 유지, 보수하는 데에 어려움이 있을 수 있다는 것을 명심해야 한다. 그들의 Rx와 코드 이해에 대해 최선을 다해 도움을 주자.
168 |
169 | **[Retrolambda](https://github.com/evant/gradle-retrolambda)**는 Android 혹은 다른 pre-JDK8 플랫폼에서 Lambda 표현 문법을 사용할 수 있도록 하는 Java 라이브러리이다. 이 라이브러리는 특히 RxJava와 같이 기능 위주 스타일의 코드를 더욱 타이트하고 읽기 좋게 만들어준다. 사용하려면, JDK8을 설치하고 이를 Android Studio 프로젝트 대화상자에서 SDK 경로로 설정한 후, `JAVA8_HOME`과 `JAVA7_HOME` 환경변수를 설정한 뒤 프로젝트 root의 build.gradle을 이렇게 설정한다:
170 |
171 | ```groovy
172 | dependencies {
173 | classpath 'me.tatarka:gradle-retrolambda:2.4.1'
174 | }
175 | ```
176 |
177 | 그리고 각각 모듈들의 build.gradle에 아래 내용을 추가하자.
178 |
179 | ```groovy
180 | apply plugin: 'retrolambda'
181 |
182 | android {
183 | compileOptions {
184 | sourceCompatibility JavaVersion.VERSION_1_8
185 | targetCompatibility JavaVersion.VERSION_1_8
186 | }
187 |
188 | retrolambda {
189 | jdk System.getenv("JAVA8_HOME")
190 | oldJdk System.getenv("JAVA7_HOME")
191 | javaVersion JavaVersion.VERSION_1_7
192 | }
193 | ```
194 |
195 | Android Studio는 Java8 lambda의 코드 지원을 제공한다. 만약 lambda가 처음이라면, 다음 항목들을 따라 시작해보자:
196 |
197 | - 하나의 메소드를 갖는 모든 인터페이스들은 "lambda와 밀접"하고, 더욱 타이트한 문법으로 묶일 수 있다.
198 | - 만약 파라메터들이 의심스럽다면, 일반 익명 내부 클래스를 작성하고 Android Studio가 lambda로 묶어주도록 해보자.
199 |
200 | **Dex 메소드 제한을 유의하고, 많은 라이브러리 사용을 피하자.** Android 앱들이 dex 파일로 패키징될 때, 65,536개의 참조 메소드 수 제한을 갖는다[[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). 제한된 메소드 수를 넘어서면 컴파일시 Fatal error를 보게될 것이다. 그렇기 때문에, 최소한의 라이브러리들을 사용하고, [dex-method-counts](https://github.com/mihaip/dex-method-counts) 툴을 사용하여 제한된 수보다 적게 유지하기 위해 어떤 라이브러리들을 사용할지 결정하자. 특히 Guava 라이브러리는 피하자. 이 라이브러리는 13,000개가 넘는 메소드를 가지고 있다.
201 |
202 | ### Activity와 Fragment
203 |
204 | Fragment와 Activity를 이용하여 Android의 구조를 가장 좋은 방법으로 설계하는 방법은 커뮤니티나 Futurice 개발자들 사이에서도 합의된 바가 없다. Square는 Fragment의 우회 대안으로 [a library for building architectures mostly with Views](https://github.com/square/mortar)를 제공하는데, 이 또한 커뮤니티 사이에서 널리 추천할만한 방식은 아니라고 생각된다.
205 |
206 | Android API의 히스토리로 인해, 막연히 Fragment가 화면상의 UI 조각이라고 떠올릴 수 있을 것이다. 즉, Fragment는 일반적으로 UI와 연관되어 있다는 것이다. Activity 또한 막연하게 그들의 라이프사이클과 상태를 관리하는 데에 중요한 컨트롤러라고 생각할 수 있다. 그러나, 다음 역할들에서 차이를 쉽게 찾아볼 수 있다: Activity는 UI 역할을 수행하고([delivering transitions between screens](https://developer.android.com/about/versions/lollipop.html)), [Fragment는 독립적으로 컨트롤러의 역할을 수행한다](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). 그래서 우리는 Fragment 혹은 Activity, 또는 View 셋 중 하나만을 이용한 구조를 선택함에 있어서 결함이 있다는 점을 파악하고 정확한 근거를 갖는 결정을 하여 조심스럽게 시작하기를 권한다. 다음은 주의해야 할 것들에 대한 조언인데, 적당히 걸러서 수용하자:
207 |
208 | - [Nested fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments)를 널리 사용하는 것은 피해야 하는데, [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/)가 발생할 수 있기 때문이다. 중첩된 Fragment는 꼭 타당한 경우(예를 들면, 수평으로 슬라이딩하는 ViewPager 내부의 Fragment들)나 잘 설명할 수 있을 만한 경우에만 사용하자.
209 | - Activity에 너무 많은 코드를 넣는 것을 피해야 한다. 가능하면 언제든지 가벼운 컨테이너로서 유지하고, 주로 라이프사이클과 다른 중요한 Android와의 인터페이싱 API를 위해서만 존재하도록 하자. 순수 Activity 보다는 단일 Fragment로 구성된 Activity가 좋다 - UI 코드를 Activity의 Fragment에 넣자. 이는 다른 잘 구성된 레이아웃, 혹은 여러 Fragment로 구성된 타블렛 화면으로 옮길 필요가 있을 때에 재사용이 가능하도록 만든다. 정확한 근거가 없는 결정이라면 Fragment와 상호 작용하지 않는 Activity는 피하자.
210 | - 앱의 내부적 동작이 Intent에 강하게 의존적인 Android 레벨의 API를 남용해서는 안된다. 이는 버그와 렉을 유발하여 Android OS나 다른 애플리케이션들에 영향을 줄 수 있다. 예를 들어, 만약 앱이 당신의 패키지 사이에서 내부적인 커뮤니케이션을 위해 Intent를 사용한다면, 앱이 OS 부팅 바로 후에 실행되었을 때 사용자 경험 상에서 몇 초간의 렉을 발생시킬 수 있다고 알려져 있다.
211 |
212 | ### Java 패키지 설계
213 |
214 | Android 애플리케이션을 위한 Java 설계 간단히 [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 간략화할 수 있다. Android에서는, [Fragment and Activity are actually controller classes](http://www.informit.com/articles/article.aspx?p=2126865) 라고 설명되는데, 다른 면에서 Fragment와 Activity들은 명시적으로 사용자 인터페이스, 즉 View 이기도 하다.
215 |
216 | 그렇기 때문에, Fragment(혹은 Activity)를 정확히 Conteroller나 View 구분할 수 없다. 그래서 그에 해당하는 `fragments` 패키지에 두는 것이 낫다. Activity는 이전 섹션에서의 조언에 따라 최상위 패키지에 둘 수 있다. 2, 3개 이상의 Activity들을 계획하고 있다면, `activities` 패키지를 만들어 두자.
217 |
218 | 다른 경우에는, API 응답에 대한 JSON 파서에 의해 채워진 POJO들을 담는 `models` 패키지, 커스텀 View, Notification, Action bar view, Widget 등을 담는 `views` 패키지를 두어 설계가 일반적인 MVC로 표현될 수 있다. Adapter들은 데이터와 View들 사이에 존재하는 gray matter라고 할 수 있지만, 일반적으로 `getView()`를 통해 View들을 추출하는 데에 필요하기 때문에 `views` 패키지 안에 `adapters`라는 서브패키지로 둘 수 있다.
219 |
220 | Controller 클래스들은 애플리케이션 전체에, Android 시스템에 가깝게 존재한다. 이들은 `managers` 패키지에 둘 수 있다. "DateUtils"와 같은 다양한 데이터 처리 클래스들은 `utils` 패키지에, 백엔드와 인터랙션하는 역할을 맡는 클래스들은 `network` 패키지에 두자.
221 |
222 | 종합적으로, 백엔드와 가까운 것부터 유저와 가까운 순서대로 정렬해보면 이렇다:
223 |
224 | ```
225 | com.futurice.project
226 | ├─ network
227 | ├─ models
228 | ├─ managers
229 | ├─ utils
230 | ├─ fragments
231 | └─ views
232 | ├─ adapters
233 | ├─ actionbar
234 | ├─ widgets
235 | └─ notifications
236 | ```
237 |
238 | ### 리소스
239 |
240 | **이름 정하기.** `type_foo_bar.xml`과 같이 타입을 접두어로 두는 컨벤션을 따르자. 예시: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.
241 |
242 | **레이아웃 XML을 체계화하기.** 레이아웃 XML을 어떤 형태로 만들지 확실치 않다면, 다음 컨벤션이 도움이 될 것이다.
243 |
244 | - 한 속성당 한 줄, 들여쓰기는 4칸의 스페이스
245 | - `android:id`를 항상 첫 속성으로
246 | - `android:layout_****` 속성들을 윗쪽에
247 | - `style` 속성은 맨 아래에
248 | - 태그를 닫는 `/>`는 정렬과 새 속성 추가를 위해 독립적인 줄에
249 | - Rather than hard coding `android:text`에 하드코딩하는 것보다, Android Studio에서 사용 가능한 [Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes)를 고려하자.
250 |
251 | ```xml
252 |
253 |
260 |
261 |
269 |
270 |
271 |
272 |
273 | ```
274 |
275 | 가장 중요한 것은, `android:layout_****`를 레이아웃 XML에 두고 `android:****`를 스타일 XML에 정의하는 것이다. 이 규칙은 예외가 있지만, 일반적으로 잘 동작한다. 이는 레이아웃(위치, 여백, 크기)과 내용에 관한 속성을 레이아웃 파일에 두고, 상세한 모양(색, 안쪽 여백, 폰트)에 대한 내용은 스타일 파일에 두기 위함이다.
276 |
277 | 예외는 이런 경우가 있다:
278 |
279 | - `android:id`는 정확히 레이아웃 파일에 두어야 한다. should obviously be in the layout files
280 | - `LinearLayout`의 `android:orientation` 속성은 일반적으로 레이아웃 파일에 있는 것이 타당하다.
281 | - `android:text`는 내용을 정의하는 속성이기 때문에 레이아웃 파일에 두어야 한다.
282 | - 가끔 일반적인 스타일로 `android:layout_width`와 `android:layout_height` 속성들을 두어야 말이 될 것 같지만, 기본적으로 이들은 레이아웃 파일에 보여진다.
283 |
284 | **스타일을 사용하자.** View에 중복되는 모양이 사용되는 것은 매우 일반적인 일이기 때문에, 거의 모든 프로젝트들이 스타일을 적절히 사용해야한다. 적어도 애플리케이션에서 대부분의 텍스트 내용들은 일반 스타일을 가져야한다. 예를 들면 이렇다:
285 |
286 | ```xml
287 |
291 | ```
292 |
293 | TextView에 적용해보면:
294 |
295 | ```xml
296 |
302 | ```
303 |
304 | 아마 버튼들에도 같은 일을 해주어야 하겠지만, 멈추지 말자. 계속 진행하면서 연관되어있고 중복된 `android:****` 속성들을 일반 스타일로 묶자.
305 |
306 | **큰 스타일 파일은 다른 파일들로 나누자.** 단 하나의 `styles.xml` 파일을 가질 필요는 없다. Android SDK는 박스 외부의 파일들도 지원하는데, `styles`라는 이름엔 전혀 마법같은 무언가가 없이 파일 안에 `
295 | ```
296 |
297 | Aplicado às TextViews:
298 |
299 | ```xml
300 |
306 | ```
307 |
308 | Provavelmente irá ter de fazer o mesmo para botões, mas não pare já por aqui. Vá mais além e mova um grupo de atributos `android:****` que estejam relacionados e sejam repetidos para um estilo comum.
309 |
310 | **Divida um ficheiro de estilo grande em outros ficheiros.** Não precisa de ter apenas um ficheiro `styles.xml`. A Android SDK suporta outros ficheiros, e não há nada de mágico acerca do nome `styles`, o que importa são as tags de XML `
260 | ```
261 |
262 | Áp dụng vào TextViews:
263 |
264 | ```xml
265 |
271 | ```
272 |
273 | Bạn có thể sẽ cần làm điều tương tự với buttons, nhưng đừng chỉ dừng lại ở hai thành phần trên. Nên khai báo các thành phần `android:****` attributes liên quan và có tính lặp lại vào một file style chung.
274 |
275 |
276 | **Chia một file style lớn thành các file styles nhỏ hơn.** Bạn không cần đặt mọi thứ trong một file `styles.xml`. Android SDK hỗ trợ nhiều files khác cùng nhau, tên file sẽ không ảnh hưởng vì Android quan tâm đến nội dung trong tags `