├── LICENSE └── README.md /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 | **本规范宗旨:希望帮助更多的开发者** 2 | 3 | **本规范只是提供参考,并且参考了部分网上博文规范,在参考文章已一一列出** 4 | 5 | * **什么叫规范?** 6 | 7 | 对于某一工程作业或者行为进行定性的信息规定。主要是因为无法精准定量而形成的标准,所以,被称为规范。在平时日常开发中,编写代码如果不遵守编译器规定,编译器就会在编译的时候报错,这个规定就是这个语言的规则,有一种规定是一种人为约定成俗的,即使不按照规定也不会出错,而这种规定就叫做规范。 8 | 9 | 假如大家都不按照规范来写代码,虽然运行不会出错,但是代码会很乱,到后面也很难维护。当我们养成一种不好的代码习惯后,这种习惯也许会陪伴自己的职业生涯,也许将来面试或者工作会让自己失去很多机会。 10 | 11 | * **代码规范初心** 12 | 13 | 当遇到严重的性能问题,就不得不去做性能优化,在优化过程中,可能会面对庞大的不良(不规范)代码,也会力不从心。造成性能问题无非就是代码写得不好,而不规范的代码除了维护性,扩展性差以外,更容易引起性能问题,无数细小的不良代码所累积的性能问题是严重的,面对上述,也许最佳的解决办法就是从代码规范入手。 14 | 15 | 16 | * **代码规范的好处** 17 | 18 | 我写过没有规范的代码,也深知其危害,遵守代码规范可以说让自己赢在写代码之前上。**我自己规范代码就是一点:面向理解编程**。代码规范最直观的好处就是看起来整洁舒服,现在假如不按规范写几万行代码后,等过一段时间再看自己写的代码就会非常吃力,更不要说其他人看了,所以代码要尽可能得规范,个人觉得在怎么烂得代码注释要到位,把重点的方法写好注释,如:入参意义,方法功能等。按照软件工程的思想,注释要占整个文档的20%以上,因此注释要写的尽可能详细,格式也要规范。 19 | 1. **降低成本维护成本提高合作效率** 20 | 随着版本的迭代和代码行数的增加,开发过程中的代码质量直接影响维护和扩展成本,当有强制的统一代码规范后,每位开发者阅读他人代码就变得简单,使代码可读性大大提高,每个人看到任何一段代码都会非常熟悉,想要一个可以日后维护,扩展轻松的项目,那么制定一个开发规范是很有必要的。 21 | 22 | 2. **可以减少Bug的处理** 23 | 对输入和输出的参数进行规范(如禁用Map入参出参,非空以及必传校验),规范的异常捕抓处理(如业务类异常,系统类异常),规范的日志输出(如每个请求的唯一id,入参,当出现错误时会输出异常类型,出错行数,出错方法等)。这些规范都能避免类型空指针异常,转换异常等bug的出现,就算出现bug进行查找解决也变得更加简单。 24 | 25 | 3. **有助于代码审查** 26 | 代码审查并不是所有公司都有的开发流程,如果没有规范的代码进行审查会加重工作量和难度,代码规范能使开发统一,减少审查拿督,让代码审查有据可查,提高审查效率效果,也能促进代码审查工作的开展和实施。 27 | 28 | 4. **开发过程规范化** 29 | 通过在开发过程中采取一些规范开发来保证开发团队的代码质量,使开发过程更加规范,成就高质量代码,减少测试的投入,促进自身乃至团队的技能提高。 30 | 5. **养成习惯** 31 | 很多时候自己写的不规范代码,进行查找某个功能某个方法或者出现bug的时候进行调试的时候而乱了头绪。更何况其他人看自己代码了,像一些出名的开源框架如:Glide,okhttp写的开源库都是很规范的,但是不是规范就能代表很高水平,规范有利于来理解框架所用到的设计模式,提升自己的开发水平。想要自己达到高水平的程序员,先从小事做起,规范代码,规范自己。 32 | 33 | ### 目录 34 | * [前言](#前言) 35 | * [基本规范](#基本规范) 36 | * [开发工具Android Studio规范](#开发工具AndroidStudio规范) 37 | * [APP包命名规范](#APP包命名规范) 38 | * [分包命名规范](#分包命名规范) 39 | * [模块命名规范](#模块命名规范) 40 | * [类命名规范](#类命名规范) 41 | * [接口规范](#接口规范) 42 | * [常量命名规范](#常量命名规范) 43 | * [变量命名规范](#变量命名规范) 44 | * [方法命名规范](#方法命名规范) 45 | * [资源命名规范](#资源命名规范) 46 | * [资源布局文件命名规范](#资源布局文件命名规范) 47 | * [图片资源文件命名规范](#图片资源文件命名规范) 48 | * [图片样式文件命名规范](#图片样式文件命名规范) 49 | * [String命名规范](#String命名规范) 50 | * [Color命名规范](#Color命名规范) 51 | * [动画资源命名规范](#动画资源命名规范) 52 | * [布局资源id命名](#布局资源id命名) 53 | * [Style命名规范](#Style命名规范) 54 | * [XML规范](#XML规范) 55 | * [预览属性约定](#预览属性约定) 56 | * [版本迭代命名规范](#版本迭代命名规范) 57 | * [注释规范](#注释规范) 58 | * [方法注释](#方法注释) 59 | * [类全局变量注释规范](#类全局变量注释规范) 60 | * [方法内注释规范](#方法内注释规范) 61 | * [代码样式规范](#代码样式规范) 62 | * [代码换行规范](#代码换行规范) 63 | * [for循环规范](#for循环规范) 64 | * [类成员顺序规范](#类成员顺序规范) 65 | * [依赖第三方库规范](#依赖第三方库规范) 66 | * [异常捕抓规范](#异常捕抓规范) 67 | * [TODO规范](#TODO规范) 68 | * [FIXME规范](#FIXME规范) 69 | * [so库命名规范](#so库命名规范) 70 | * [jar包命名规范](#jar包命名规范) 71 | * [kotlin规范](#kotlin规范) 72 | * [kotlin基本规范](#kotlin基本规范) 73 | * [声明规范](#声明规范) 74 | * [源文件名称规范](#源文件名称规范) 75 | * [类头排版规范](#类头排版规范) 76 | * [格式化控制流语句规范](#格式化控制流语句规范) 77 | * [代码提交规范](#代码提交规范) 78 | * [日常开发规则](#日常开发规则) 79 | * [参考文章](#参考文章) 80 | * [最后](#最后) 81 | 82 | #### 前言 83 | * 代码规范原则 84 | 85 | * **代码简洁易懂,逻辑清晰**因为软件是需要人来维护的。这个人在未来很可能不是你。但要有前人种树,后人乘凉的精神,所以首先是为人编写程序,其次才是计算机。 86 | 87 | 1. 不要过分追求技巧,降低程序的可读性。 88 | 2. 简洁的代码可以让bug无处藏身。要写出明显没有bug的代码,而不是没有明显bug的代码。 89 | * **面向变化编程,而不是仅仅面向需求编程**本次迭代不能仅仅为了当前的需求,写出扩展性强,易修改的程序才是负责任的做法,对自己负责,对公司负责。 90 | * **先保证程序的正确性,防止过度工程**`过度工程(over-engineering)`:在正确可用的代码写出之前就过度地考虑扩展,重用的问题,使得工程过度复杂,`《编程的智慧》`里面有说到: 91 | 1. 先把眼前的问题解决掉,解决好,再考虑将来的扩展问题。 92 | 2. 先写出可用的代码,反复推敲,再考虑是否需要重用的问题 93 | 3. 先写出可用,简单,明显没有bug的代码,再考虑测试的问题 94 | 95 | * 代码规范目标 96 | 97 | * **提升质量意识,降低问题发生和维护成本** 98 | * **统一标准,提升协作效率** 99 | * **追求卓越工匠精神,打磨精品代码** 100 | * **规范自己,榜样他人** 101 | 对于有代码例子中,“说明”对代码进行了扩展和解释,“正例”意思是建议提倡这种编码方式;“反例”意思是错误的编码方式,不提倡甚至禁止这种编码习惯方式。 102 | 103 | #### 基本规范 104 | * 禁止用中文定义类,常量,变量,方法名以及`key` 105 | * 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束 106 | * 删除未使用的局部变量、方法参数、私有方法、字段和多余的括号,无用的引入,禁用s1,s2,s3,y1这种命名 107 | * 每次只声明一个变量,不要使用组合声明 108 | ``` 109 | //反例 110 | int minNumber,maxNumber 111 | //正例 112 | int minNumber; 113 | int maxNumber; 114 | ``` 115 | * 拆分臃肿方法,确保每个方法只做一件事,单一职责 116 | * 方法之间必须有空行 117 | * 任何地方不要拼错单词 118 | * 代码尽量不要出现中文,注释除外,代码中通过`strings.xml`来引用显示中文 119 | * 布局文件中的字体大小,`margin`和`padding`的值也要放在`dimens.xml`中 120 | * 在一个`View.OnClickListener`中处理所有的点击事件逻辑,集中方便管理 121 | * `strings.xml`中使用`%1d`实现字符串的通配 122 | * 如没有特殊需求说明,TextView中设置字体大小单位统一用spp 123 | * xml中用`layout_marginStart/End`来代替`layout_marginLeft/Right`,`padding`同理 124 | * 数据类型转换一定要加校验 125 | * 每个switch语句都包含一个default语句组,即使它什么代码也不包含 126 | * 禁止在四大组件(Activity,Service,BroadcastReceiver,ContentProvider)中主线程做耗时操作 127 | * 注册反注册要成对出现(Eventbus,广播) 128 | * 资源对象不再使用时要及时关闭(Cursor,文件流,Bitmap,视频),当确保不在使用这些资源时,必须关闭,否在会引起泄漏(Cursor.close(),BufferefReader.close(),Bitmap.recycle())。**注意:在 2.3.3 及以下需要调用 recycle()函数,在 2.3.3 以上 GC 会自动管理** 129 | ``` 130 | if (Build.VERSION.SDK_INT <= 10) { 131 | bitmap.recycle(); 132 | } 133 | bitmap = null; 134 | ``` 135 | * 禁止在非UI线程(一般指主线程)进行view的相关操作 136 | * 在`View`中的`onDraw`方法尽可能少频繁创建对象 137 | * 合理布局,有效运用``、``、``标签 138 | * 不要通过Intent在基础组件传递大数据(binder transaction 缓存为1MB) 139 | * 操作本地数据库放在子线程中去,多线程写入数据库时,需要使用事务,以免出现同步问题 140 | * 使用png或者jpg图片时,一定要自己先使用压缩工具(tinypng)去进行压缩处理 141 | * 考虑使用`Webp`格式代替`png`格式的图片 142 | * 不要把敏感信息打印到log中,线上一定关闭所有log输出 143 | * 用`equals`方法时,用`xxxx.equals(object)`,不用`object.equals(xxxx)`,因为object对象有可能为空,导致空指针异常 144 | * 一个类不被继承时,要用final来修饰 145 | * 看情况来用访问修饰符`public,private,protect`,如:一个字段或者方法不需要被外部访问,用`private`修饰 146 | * 应用的图标放在**mipmap**目录下,其他图片资源放在`drawable`目录下 147 | * 不要在**Application**对象中缓存数据(因为有可能会因系统内存不足而进行回收,但是这时候重新打开应用的时候,会创建一个新的Application对象,但是可能会启动回收前用户打开的界面,这样会造成缓存数据重新初始化,造成不可预期的结果) 148 | * 判断是否空集合用`Collection.isEmpty`比`Collection.size == 0`获得更好的性能,判断是否为`null`可以用`CollectionUtils.isEmpty(collection)` 149 | * 循环使用`StringBuilder`比`String`拼接,替换字符串更优 150 | * 注意Map类集合K/V能不能存储null值得情况,如下表格: 151 | | 集合类 | Key | Value | Super | 说明 | 152 | | :-----: | :----: | :----: | :---:| :---: | 153 | | Hashtable | 不允许为null | 不允许为null | Dictionary | 线程安全 154 | | ConcurrentHashMap | 不允许为null | 不允许为null | AbstractMap | 分段锁技术 155 | | TreeMap | 不允许为null | 允许为null | AbstractMap | 线程不安全 | 156 | | HashMap | 允许为null | 允许为null | AbstractMap | 线程不安全 | 157 | 158 | * 如果使用到了设计模式,建议在类名中体现具体模式,如: 159 | ``` 160 | public class ComponentFactory 161 | public class BufferStrategy 162 | public class ScrollerProxy 163 | ``` 164 | * 工具类中屏蔽构造函数,一般来说工具类是一堆静态字段和函数的集合,其不应该被实例化 165 | ``` 166 | public class MathUtils { 167 | public static final double PI = 3.1415926D; 168 | //需要加这一行 169 | private MathUtils() {} 170 | public static int sum(int a, int b) { 171 | return a + b; 172 | } 173 | } 174 | ``` 175 | * 调用工具类尽可能简单,如:`ToastUtils.show()` 176 | * 文件、网络`IO`缓存,使用有缓存机制的输入流,如: 177 | ``` 178 | BufferedInputStream替代InputStream 179 | BufferedReader替代Reader 180 | BufferedReader替代BufferedInputStream 181 | ``` 182 | * 使用JSON工具类,不要手动解析和拼装数据 183 | * 尽量在合适的场合使用单例,使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,进程中类只想有一个实例(对象)时,使用单例模式: 184 | * 控制资源的使用,通过线程同步来控制资源的并发访问 185 | * 控制实例的产生,以达到节约资源的目的 186 | * 控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信 187 | * 使用 AS 自带的 Lint 来优化代码结构 188 | * 不要将数组声明为`public static final`因为这毫无意义,这样只是定义了引用为static final,数组的内容还是可以随意改变的,将数组声明为public更是一个安全漏洞,这意味着这个数组可以被外部类所改变 189 | * 使用同步代码块替代同步方法 190 | * 把一个基本数据类型转为字符串,`.toString()`是最快的方式、`String.valueOf`次之、数据`+`最慢 191 | * `String.valueOf()`方法底层调用了Integer.toString()方法,但是会在调用前做空判断 192 | * `Integer.toString()`方法就不说了,直接调用了 193 | * `i + “”`底层使用了StringBuilder实现,先用append方法拼接,再用toString()方法获取字符串 194 | * 对资源的close()建议分开操作,虽然有些麻烦,却能避免资源泄露。我们想,如果没有修改过的代码,万一```XXX.close()```抛异常了,那么就进入了catch块中了,```YYY.close()```不会执行,YYY这块资源就不会回收了,一直占用着,这样的代码一多,是可能引起资源句柄泄露的。而改为下面的写法之后,就保证了无论如何XXX和YYY都会被close掉 195 | ``` 196 | try 197 | { 198 | XXX.close(); 199 | YYY.close(); 200 | } 201 | catch (Exception e) 202 | { 203 | ... 204 | } 205 | 206 | //建议修改为: 207 | try 208 | { 209 | XXX.close(); 210 | } 211 | catch (Exception e) 212 | { 213 | ... 214 | } 215 | try 216 | { 217 | YYY.close(); 218 | } 219 | catch (Exception e) 220 | { 221 | ... 222 | } 223 | ``` 224 | 225 | * 静态类、单例类、工厂类将它们的构造函数置为`private`,这是因为静态类、单例类、工厂类这种类本来我们就不需要外部将它们new出来,将构造函数置为private之后,保证了这些类不会产生实例对象 226 | * 枚举的属性字段必须是私有不可变,枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改。理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的 `Setter`方法,最好加上`final`修饰符 227 | ``` 228 | //反例 229 | public enum UserStatus { 230 | DISABLED(0, "禁用"), 231 | ENABLED(1, "启用"); 232 | 233 | public int value; 234 | private String description; 235 | 236 | private UserStatus(int value, String description) { 237 | this.value = value; 238 | this.description = description; 239 | } 240 | 241 | public String getDescription() { 242 | return description; 243 | } 244 | 245 | public void setDescription(String description) { 246 | this.description = description; 247 | } 248 | } 249 | 250 | //正例 251 | public enum UserStatus { 252 | DISABLED(0, "禁用"), 253 | ENABLED(1, "启用"); 254 | 255 | private final int value; 256 | private final String description; 257 | 258 | private UserStatus(int value, String description) { 259 | this.value = value; 260 | this.description = description; 261 | } 262 | 263 | public int getValue() { 264 | return value; 265 | } 266 | 267 | public String getDescription() { 268 | return description; 269 | } 270 | } 271 | 272 | 273 | ``` 274 | * 小心`String.split(String regex)`,字符串String的`split`方法,传入的分隔字符串是正则表达式!部分关键字(比如`.[]()\|`等)需要转义 275 | ``` 276 | "a.ab.abc".split("."); // 结果为[] 277 | "a|ab|abc".split("|"); // 结果为["a", "|", "a", "b", "|", "a", "b", "c"] 278 | 279 | "a.ab.abc".split("\\."); // 结果为["a", "ab", "abc"] 280 | "a|ab|abc".split("\\|"); // 结果为["a", "ab", "abc"] 281 | ``` 282 | 283 | 284 | #### 开发工具AndroidStudio规范 285 | 因为目前都是使用Android Studio来进行开发安卓开发,所以工具基于Android Studio来说明。 286 | 287 | * 【强制】使用稳定的Android Studio版本进行开发,Android Studio会有四个版本分别是: 288 | * Stable Channel(稳定版),我们一般使用这个版本进行开发 289 | * Beta Channel(预发布版本),这个是预发布版本,在发布稳定版之前先发布这个版本,并获取问题反馈进行修复,Beta版本会将与一个新的稳定版本一起被更新 290 | * Dev Channel(开发版本),金丝雀版本经过完整测试后会提到这个版本 291 | * Canary Channel(金丝雀版本),大约周更,这是最早的发布的版本,这个版本会有下一个稳定版本最新的功能 292 | **建议:可以同时安装稳定版和金丝雀版本**。 293 | 294 | 我们可以选择【Help】- 【Check for Updates...】进行查看对应版本更新 295 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b5f155e30ee94ae4b291855414b511e4~tplv-k3u1fbpfcp-zoom-1.image) 296 | 297 | 点击【Configure updatea】进行跟新配置,查看对应不同的版本 298 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/255366090be84d0fa0aff1ddc9f08d69~tplv-k3u1fbpfcp-zoom-1.image) 299 | 300 | * 【推荐】使用统一版本的Android Stuido进行开发,如:4.1.1 301 | * 【强制】使用统一的gradle构建工具版本,在项目根目录【gradle】-【gradle-wrapper.properties】进行设置 302 | * 【强制】使用统一的gradle插件版本配置,在项目根目录【build.gradle】下进行设置 303 | * 【强制】编码格式为UTF-8 304 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f80bbc778014f03b29fe89bcc3d1a16~tplv-k3u1fbpfcp-zoom-1.image) 305 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f861874b8d3441998e6fa6c23736023d~tplv-k3u1fbpfcp-zoom-1.image) 306 | * 【强制】删除多余的import,手动清除可以点击菜单栏【Code】-【Optmize Imports】,可以设置自动清除 307 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd53c79adee444038b4ae04f37c55959~tplv-k3u1fbpfcp-zoom-1.image) 308 | * 【强制】禁止类文件中出现`import.*`,意思就是导入的类包必须是单路径引用,必须列出详细的import内容,可以设置下自动合并import的包名 309 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b56389c512a4454e8e3796f157d029b5~tplv-k3u1fbpfcp-zoom-1.image) 310 | kotlin设置**Use single name import**即可,Android Studio默认就是这个选项 311 | 312 | * 【推荐】每行代码字符数不超过160个字符,在【Editor】-【Code Style】设置,Android Studio 默认就是这个字符数 313 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/06033f32c49043dbbc22861da32f0e7b~tplv-k3u1fbpfcp-zoom-1.image) 314 | 315 | * 【强制】每个类必须带有版权信息,创建人信息,描述,对自己代码负责,可根据自己公司要求做出变化 316 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0971a74f321e4a3dae5e2f156345692c~tplv-k3u1fbpfcp-zoom-1.image) 317 | 318 | * 【强制】必须安装[阿里巴巴代码](https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines)约束插件 319 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/497af36365be4873906aedb8e1f36812~tplv-k3u1fbpfcp-zoom-1.image) 320 | 到这里开发工具就设置完毕。 321 | 322 | #### APP包命名规范 323 | * 【强制】全部小写,以防止和类名、接口名冲突,若有多个单词则直接连接在一起,不能有下划线 324 | * 符合规范的示例:`com.example.deepspace` 325 | * 不符合规范的示例:`com.wxample.deepSpace`、`com.example.deep_space` 326 | 327 | * 【强制】包名前缀必须是能区分一个组织的顶级域名,倒叙写,比如`com.apple` 328 | 329 | * 【强制】包名子路径不能包含java关键词,比如int、protect。 330 | 331 | #### 分包命名规范 332 | 一个项目肯定会分很多的包,不可能把全部文件放在一个包下,分包是为了**统一管理项目文件**。 333 | * 【推荐】按功能或者作用进行分包,如:utils(工具)、widget(组件)、adapter(适配器),按功能分包容易找到对应的类位置、容易管理、高度抽象、更容易封装。 334 | 335 | * 【强制】不要在对应包名放无关的类或者不属于这个包下的类 336 | #### 模块命名规范 337 | 很多时候app会分很多模块,这些模块命名必须简单易懂。 338 | * 【强制】不能有大写中文,全部小写英文 339 | ``` 340 | base 341 | home 342 | live 343 | database 344 | ``` 345 | 346 | * 【强制】模块混淆配置,不使用`proguardFiles`语句,使用`consumerProguardFiles`,理由如下: 347 | * `consumerProguardFiles`下的proguard会被打进aar包中,而`proguardFiles`配置的proguard不会被打进aar中。 348 | * `proguardFiles`下的proguard文件只作用于库文件代码,只在编译发布aar的时候有用,在将库文件作为模块添加到App模块中,库文件的`consumerProguardFiles`配置的proguard文件则会追加到App模块的proguard配置文件中,作用于整个app。 349 | 350 | ``` 351 | buildTypes { 352 | release { 353 | //反例 354 | //proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 355 | //正例 356 | consumerProguardFiles 'proguard-rules.pro' 357 | } 358 | } 359 | ``` 360 | 361 | * 【推荐】增加资源命名前缀限制,为了避免模块间资源合并冲突,可以用模块名或者功能作为前缀 362 | ``` 363 | android { 364 | //限定资源前缀命名 365 | resourcePrefix "wechat_" 366 | } 367 | ``` 368 | 369 | #### 类命名规范 370 | * 【强制】 类名必须按照`UperCamelCase`(大驼峰)风格类命名,避免单词缩写 371 | 372 | * 业务类:按照**模块+类型**进行命名 373 | * 技术类:按照**作用+类型**进行命名 374 | 375 | | 类 | 描述 | 例子 | 376 | | :-----: | :----: | :----: | 377 | | 基础类 | Base + 类型 | BaseActivity
BaseFragment 378 | | Activity 类 | 界面+Activity | HomeActivity 379 | | Fragment类| 界面+Fragment | HomeFragment 380 | | 自定义View | 功能+View/ViewGroup(组件类型) | CircleView/ShapeViewGroup 381 | | Adapter类 | 功能+Adapter | ShoeDetailAdapter 382 | | 工具类 | 功能+Utils | LogUtils(日志类)
GsonUtils(json解析类)
ThreadPoolUtils(线程类) 383 | | 抽象类 | Abstract+类型 | AbstractCircleView
AbstractTest 384 | | 异常类 | 异常类型+Exception | NullPointerException(空指针异常)
ArithmeticException(运算错误异常) 385 | | 接口类 | 功能(业务模块)+Interface
功能+Listener | UserInterface
OcrTextInterface
OnClickListener 386 | | 接口实现类 | 功能(业务模块)+InterfaceImpl | UserInterfaceImpl
OcrTextInterfaceImpl 387 | 388 | #### 接口规范 389 | * 【推荐】如果功能比较简单,单用在某个类伤,接口可以写在内部,如果方法功能比较多,建议抽取写成外部,如: 390 | ``` 391 | public class TextClickUtils { 392 | 393 | public interface OnClickToWebListener{ 394 | void goWeb(); 395 | } 396 | 397 | private OnClickToWebListener mOnClickToWebListener; 398 | 399 | public void setOnClickWebListener(OnClickToWebListener mOnClickToWebListener){ 400 | this.mOnClickToWebListener = mOnClickToWebListener; 401 | } 402 | } 403 | 404 | ``` 405 | ``` 406 | public interface OnHttpListener { 407 | /** 408 | * 请求开始 409 | */ 410 | default void onStart(Call call) {} 411 | 412 | /** 413 | * 请求成功 414 | */ 415 | void onSucceed(T result); 416 | 417 | /** 418 | * 请求出错 419 | */ 420 | void onFail(Exception e); 421 | 422 | /** 423 | * 请求结束 424 | */ 425 | default void onEnd(Call call) {} 426 | } 427 | ``` 428 | 429 | * 【推荐】接口实现的类所实现方法要有@link 430 | 431 | ``` 432 | public class HttpCallback implements OnHttpListener,OnDownloadListener { 433 | 434 | /** 435 | * {@link OnHttpListener} 436 | * @param call 437 | */ 438 | @Override 439 | public void onStart(Call call) { 440 | 441 | } 442 | 443 | 444 | @SuppressWarnings("unchecked") 445 | @Override 446 | public void onSucceed(T result) { 447 | 448 | } 449 | 450 | @Override 451 | public void onFail(Exception e) { 452 | 453 | } 454 | 455 | @Override 456 | public void onEnd(Call call) { 457 | 458 | } 459 | 460 | /** 461 | * {@link OnDownloadListener} 462 | * @param file 463 | */ 464 | @Override 465 | public void onStart(File file) { 466 | 467 | } 468 | 469 | @Override 470 | public void onProgress(File file, int progress) { 471 | 472 | } 473 | 474 | @Override 475 | public void onComplete(File file) { 476 | 477 | } 478 | 479 | @Override 480 | public void onError(File file, Exception e) { 481 | 482 | } 483 | 484 | @Override 485 | public void onEnd(File file) { 486 | 487 | } 488 | } 489 | ``` 490 | 方便快速找到接口类的位置 491 | 492 | #### 常量命名规范 493 | 常量命名模式是`CONSTANT_CASE`,全部字母大写,用下划线分割单词,是名词或者动词类型,禁止拼音和英文混合方式,每个常量都是一个静态`final`字段,但不是所有静态`final`字段都是常量,决定一个字段是否常量时,考虑它的生命周期是否永远不变化,只有一直不变才标示是一个常量,例如: 494 | ``` 495 | // 常量 496 | static final int NUMBER = 5; 497 | static final ImmutableListNAMES = ImmutableList.of("Ed", "Ann"); 498 | static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable 499 | static final SomeMutableType[] EMPTY_ARRAY = {}; 500 | enum SomeEnum { ENUM_CONSTANT } 501 | 502 | // 不是常量 503 | static String nonFinal = "non-final"; 504 | final String nonStatic = "non-static"; 505 | static final SetmutableCollection = new HashSet(); 506 | static final ImmutableSetmutableElements = ImmutableSet.of(mutable); 507 | static final Logger logger = Logger.getLogger(MyClass.getName()); 508 | static final String[] nonEmptyArray = {"these", "can", "change"}; 509 | ``` 510 | 511 | ``` 512 | //正例 513 | public static final int CAR_FRONT_LAMP = 2; 514 | //反例 515 | public static final int car_front_lamp = 2; 516 | ``` 517 | **kotlin一定要 const val来定义**,如 518 | ``` 519 | const val MAX_STOCK_COUNT = 5 520 | ``` 521 | 522 | 523 | #### 变量命名规范 524 | 变量局部变量、全局变量,统一规则: 525 | 526 | * 是名词或者动词类型,禁止拼音和英文混合方式 527 | * 变量按照`lowerCamelCase`风格,必须遵从小驼峰形式 528 | * 常量命名全部大写,单词间用下划线隔开,为了意思表达完整,不要嫌弃名字过长 529 | * 局部变量或者公开的成员变量以作用来命名。如: 530 | ``` 531 | public String mobile 532 | public TextView mobileTextView 533 | public LinearLayout mobileLinearLayout 534 | ``` 535 | * 【推荐】非公开的成员变量以小`m`开头,统一 536 | ``` 537 | private String mMobile 538 | private TextView mMobileTextView 539 | private LinearLayout mMobileLinearLayout 540 | ``` 541 | * 【强制】布尔值命名规范,不要在前缀加is,部分框架解析会引起序列化错误(com.alibaba.fastjson.util.TypeUtils.computeGetters有对is开头的方法进行处理) 542 | ``` 543 | //反例 544 | private boolean isPrintLog 545 | //正例 546 | private boolean printLog 547 | ``` 548 | * 【推荐】静态变量则用小s开头,统一 549 | ``` 550 | private static ProxySelector mProxySelector 551 | ``` 552 | 553 | 554 | | 类型 | 描述 | 例子 | 555 | | :-----: | :----: | :----: | 556 | | 变量 | 遵从`lowerCamelCase` | private boolean mDestroyed
var doorNumber:Int = 5 557 | | 临时变量 | 整型:`i,j,k` | for (int i = 0; i < len; i++) 558 | 559 | **注意:Kotlin中只读变量用`val`,可变变量用`var`** 560 | 561 | * 【推荐】若一个类中有常量或者变量的时候,声明常量在前,变量在后,如: 562 | ``` 563 | public class DemoTest { 564 | /* 565 | * 注释.... 566 | */ 567 | public static final int RESULT_CANCELED = 0; 568 | /* 569 | * 注释.... 570 | */ 571 | private int mTitleColor = 0; 572 | } 573 | ``` 574 | * 【强制】 在long或者Long赋值时,数值后使用的大写L,不能是小写的l,小写容易跟数字1混淆,造成误解 575 | 如: 576 | ``` 577 | //反例 578 | Long a = 2l,//不知道是21还是2 579 | 580 | //正例 581 | Long number = 2L; 582 | ``` 583 | 584 | * 【推荐】 不要使用一个常量类维护所有常量,要按功能去进行分类,分开管理,放在一个类中,日而久之,杂乱无章,不利于理解和维护 585 | 586 | #### 方法命名规范 587 | * 【强制】方法名都以`lowerCamelCase`风格编写,是名词或者动词类型,禁止拼音和英文混合方式 588 | 589 | | 方法 | 说明 | 590 | | :-----: | :----: | 591 | | initXXX() | 初始化(initData、initView) | 592 | | getXXX() | 返回某个值(getTextSize、getTextPadding) | 593 | | setXXX() | 设置某个属性值(setTextSize、setTextPadding) | 594 | | checkXXX()、isXXX() | 返回布尔类型的值(checkLogin) | 595 | | showXXX() | 显示View或者页面提示信息(showNetworkMessage) | 596 | | updateXXX() | 更新数据或者更新页面(updateLoginMessage) | 597 | | saveXXX()、insertXXX() | 保存数据(saveLoginMessage)、插入数据(insertArticle) | 598 | | resetXXX() | 重置数据或者视图状态等(resetLoginMessage)、插入数据(insertArticle) | 599 | | clearXXX() | 清除数据(clearLoginMessage) | 600 | | removeXXX() | 移除数据(removeLoginMessage) | 601 | | deleteXXX() | 删除数据(deleteLoginMessage) | 602 | | queryXXX() | 查询数据(queryLoginMessage) | 603 | 604 | #### 资源命名规范 605 | * 【强制】以名词或者动词类型,中间以`_`为分隔符,禁止拼音和英文混合方式 606 | 607 | ##### 资源布局文件命名规范 608 | * 【推荐】**模块+作用+类型**进行命名,采用下划线命名方式,如: 609 | 610 | | 布局 | 例子 | 611 | | :-----: | :----: | 612 | | activity | home_activity.xml | 613 | | fragment | home_fragment.xml | 614 | | adapter | home_articles_adapter.xml | 615 | | dialog | home_articles_dialog.xml | 616 | | popupWindow | home_messgae_pop | 617 | | item | home_message_item | 618 | | menu | menu_item.xml | 619 | 620 | 对`layout`可以进行分包处理,在`build.gradle`文件下配置,例子如下: 621 | ``` 622 | android { 623 | main { 624 | res.srcDirs = 625 | [ 626 | 'src/main/res/layouts/activitys', 627 | 'src/main/res/layouts/fragments', 628 | 'src/main/res/layouts/adapters', 629 | 'src/main/res/layouts/items', 630 | 'src/main/res/layouts/dialogs', 631 | 'src/main/res/layouts', 632 | 'src/main/res' 633 | 634 | ] 635 | } 636 | } 637 | ``` 638 | 配置完编译一下,结构如下: 639 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/53fb09f4a84542869dbc61f3d6c5da32~tplv-k3u1fbpfcp-zoom-1.image) 640 | 641 | ##### 图片资源文件命名规范 642 | * 【推荐】如果是与业务相关的,直接以**模块(页面)+用作view的缩写+类型**,采用下划线命名方式,如: 643 | 644 | | 图片 | 例子 | 645 | | :-----: | :----: | 646 | | png | home_iv_cancel_ic.png(首页关闭图标) | 647 | | png | wecaht_iv_share_link_ic.png(wechat模块下分享链接图标) | 648 | | jpg | message_tv_delete_ic.jpg(message模块下删除图标) | 649 | | jpg | message_rl_main_bg.jpg(message模块下主页的背景图片) | 650 | 651 | 652 | * 【推荐】如果有多种形态,如按钮选择器:`btn_xxx.xml`(selector) 653 | 654 | | 名称 | 说明 | 655 | | :-----: | :----: | 656 | | btn_xx | 按钮图片使用`btn_整体效果`(selector) | 657 | | btn_xx_normal | 分割线`控件_模块_颜色` | 658 | | btn_xx_pressed | 按钮图片使用`btn_点击时候效果` | 659 | | btn_xx_focused | 聚焦效果`state_focused` | 660 | | btn_xx_disabled | (false)不可用效果 `state_enabled`  | 661 | | btn_xx_checked | 选中效果`state_checked` | 662 | | btn_xx_selected | 选中效果`state_selected` | 663 | | bbtn_xx_hovered | 悬停效果`state_hovered` | 664 | | btn_xx_checkable | 可选效果 `state_checkable` | 665 | | btn_xx_activated | 激活的 `state_activated` | 666 | | btn_xx_windowfocused | state_window_focused | 667 | 668 | 669 | * 【推荐】如果是多个业务都用一个图标,或者和业务无相关,直接以**作用+类型**,采用下划线命名方式,如: 670 | 671 | | 图片 | 例子 | 672 | | :-----: | :----: | 673 | | png | close_ic.png(关闭图标) | 674 | | png | share_link_ic.png(分享链接图标) | 675 | | jpg | copy_ic.jpg(复制图标) | 676 | | jpg | splash_bg.jpg(复制图标) | 677 | 678 | 有些开发者以`类型`开头命名(`ic_copy.png`、`ic_share_link.png`、`bg_splash.jpg`)也没问题,这个看自己和公司规范 679 | 680 | ##### 图片样式文件命名规范 681 | * 【推荐】如果是与业务相关的,直接以**模块(页面)+用作view的缩写+类型**,采用下划线命名方式,如: 682 | 683 | | 名称 | 例子 | 684 | | :-----: | :----: | 685 | | selector | login_btn_rect_selector.xml(登录按钮直角样式) | 686 | | selector | live_share_tv_selector.xml(直播分享样式) | 687 | | selector | register_btn_round_selector.xml(注册按钮圆角样式) 688 | 689 | * 【推荐】如果是非业务的资源,以**作用+用作view的缩写+类型来命名**,采用下划线命名方式,如: 690 | 691 | | 名称 | 例子 | 692 | | :-----: | :----: | 693 | | selector | btn_rect_selector.xml(通用按钮直角样式) | 694 | | selector | top_btn_round_selector.xml(通用上部分按钮圆角样式) | 695 | 696 | 有些开发者以`类型`开头命名(`selector_btn_rect.xml`、`selector_top_btn_round.xml`)也没问题,这个看自己和公司规范 697 | 698 | ##### String命名规范 699 | * 【推荐】项目适配了多语种,没有特殊需要 则严禁写死在代码里或者布局文件中,将资源定义在`string.xml`文件中 700 | * 【推荐】以**模块(页面)+功能**,采用下划线命名方式,如: 701 | ``` 702 | 703 | 取消 704 | 保存 705 | 搜索历史 706 | 请输入搜索关键字 707 | 708 | 709 | 设置语言模式 710 | 设置 711 | 退出 712 | 清除缓存 713 | 714 | 715 | 注册 716 | 注册账号 717 | 请输入长度不超过16位,包含数字英文大小写字母的账号 718 | 请输入密码 719 | 请在一次输入密码 720 | 密码输入错误 721 | 722 | 723 | 广场 724 | 分享文章成功 725 | 请输入文章标题 726 | 请输入以:http或者https开头的文章链接 727 | 分享文章 728 | ``` 729 | 730 | * 【推荐】有时候可能多个模块都需要用,以**通用前缀+作用**,采用下划线命名方式,如: 731 | 732 | ``` 733 | 加载中... 734 | 取消 735 | 确定 736 | 保存 737 | ``` 738 | 739 | ##### Color命名规范 740 | * 【推荐】适配了深色模式下,没有特殊需求严禁直接定义在布局文件中 741 | * 【推荐】以**模块(页面)+作用**,采用下划线命名方式,如: 742 | ``` 743 | 744 | #FFFFFFFF 745 | 746 | #FFFFFFFF 747 | 748 | #FFFFFFFF 749 | 750 | #FFFFFFFF 751 | ``` 752 | * 【推荐】有时候可能多个模块需要引用,以**通用前缀+作用**,采用下划线命名方式,如: 753 | ``` 754 | 755 | #FFFFFFFF 756 | 757 | #FFFFFFFF 758 | 759 | #FFFFFFFF 760 | ``` 761 | 762 | * 【推荐】另外还有一种命名方式`以颜色值命名`,如: 763 | ``` 764 | 765 | 766 | #FFFFFF 767 | 768 | #DBDBDB 769 | 770 | #939393 771 | 772 | #5F5F5F 773 | 774 | #323232 775 | 776 | 777 | 778 | #27D34D 779 | 780 | #2A91BD 781 | 782 | #FF9D2F 783 | 784 | #FF432F 785 | ``` 786 | 命名可以在这个[https://www.matools.com/color/](https://www.matools.com/color/)获取 787 | 788 | 789 | * 【不推荐】 在实际过程中,会遇到下面这种命名方式,如: 790 | ``` 791 | #999999 792 | ``` 793 | 这种命名规则虽然以颜色值为命名,看上去很清楚显示用了什么颜色值,但是随着版本迭代,假如后面项目有500个地方用了这个颜色值,但是不知道这个颜色值是用来干什么的,可能后面某个需求某些个按钮文本颜色更改(将这个颜色值改为另外一个颜色),那么是,这时候你就要区分这500个地方,哪些需要改哪些不需要改。 794 | 795 | ##### 动画资源命名规范 796 | Android分为属性动画和视图动画,视图动画包括补间动画和帧动画,属性动画文件需放在`res/animator/`下,视图动画放在`res/anim/`下。 797 | * 【推荐】以`模块(页面)+用作view+作用`,采用下划线命名方式,如: 798 | 799 | | 名称 | 说明 | 800 | | :-----: | :----: | 801 | | login_btn_fade_in | 登录模块按钮淡入 | 802 | | login_btn_fade_out | 登录模块按钮淡出 | 803 | | login_tv_push_down_in | 登录模块文本从下方推入 | 804 | | login_tv_oush_down_out | 登录模块文本从下方推出 | 805 | | message_btn_zoom_enter | 消息模块按钮变形进入 | 806 | | message_tv_slide_in | 消息模块文本滑动进入 | 807 | | login_tv_oush_down_out | 登录模块文本从下方推出 | 808 | 809 | 810 | ##### 布局资源id命名 811 | * 【推荐】以`控件缩写+模块名+作用`,采用下划线命名方式,如: 812 | 813 | | 类型 | 规范 | 示例 | 解释 814 | | :-----: | :----: | :----: | :----: | 815 | | TextView | tv_xxx | tv_login_account | 登录界面账号文本 816 | | EditText | et_xxx_| et_login_account | 登录界面账号输入 817 | | ImageView | iv_xxx_| iv_login_head | 登录界面头像显示 818 | | CheckBox | cb_xxx_| cb_login_save_password | 登录界面记住密码选择 819 | | LinearLayout | ll_xxx_| ll_login_account | 登录界面账号线性布局 820 | | Recycleview | rv_xxx_| rv_home_article | 首页界面文章列表 821 | | ConstraintLayout | cl_xxx_| cl_home_root | 首页界面根布局 822 | | FrameLayout | fl_xxx_| fl_mine_root | 我的界面根布局 823 | 824 | ##### Style命名规范 825 | ` 839 | 840 | 841 | 846 | 847 | 848 | 851 | 852 | ``` 853 | ``` 854 | 855 | 858 | 859 | 860 | 863 | 864 | 865 | 869 | 870 | ``` 871 | 872 | #### XML规范 873 | 874 | * 【推荐】没有子节点的情况下,以`/>`来结尾 875 | ``` 876 | 879 | 880 | 883 | 884 | ``` 885 | 886 | * 【推荐】ImageView宽高定义成`match_parent`,另外一项不能写死,而是应该使用`wrap_content`,否则可能因为比例不对导致变形,另外需要使用`android:adjustViewBounds="true"`,进行根据图片宽高调整自己的宽高 887 | ``` 888 | 893 | ``` 894 | 895 | ##### 预览属性约定 896 | * 【推荐】在每个布局中定义`tools:context`这样子方便找到对应的类 897 | ``` 898 | 904 | 905 | 906 | ``` 907 | 在`tools:context=".ui.Fragment.MineFragment"`按住`crtl`并且点击鼠标即可快速找到对应的类 908 | 909 | 在适配器布局同理一样,有布局文件都可以添加: 910 | ``` 911 | 912 | 918 | 919 | 920 | ``` 921 | * 【推荐】如果**TextView**显示字符串是一成不变,可以直接定义在布局文件里,如果是动态变化,应该使用`tools:text`预览属性,而不应该使用`android:text`,为什么呢?因为在写布局代码的时候,有些效果是在运行之后才能看到,比如:**TextView**在xml中没有设置任何字符,而是在类(activity或者fragment)中设置的,但是为了看预览效果,就设置了`android:text`属性,很多时候告诉自己,写完代码会把这一行删了,但是很有可能忘了,到最后这些代码会在自己APP里。因此,如果要在运行时胡磊,只在设计布局有效,应该用`tools:text`,这样子运行的时候本身会被忽略,不会带进apk中,同理也可以用在`ImageView`等。 922 | 923 | #### 版本迭代命名规范 924 | * 【推荐】版本名至少应该由三段整数组成,中间以`.`分隔,例如微信:8.0.11 925 | ``` 926 | versionName = "8.0.11" 927 | ``` 928 | * 第一段:重大版本,架构升级,UI风格大改版,业务重构等改变特大时候+1 929 | * 第二段:强制需求版本,每个需求完成发版+1 930 | * 第三段:非强制需求版本,每个需求完成发版+1 931 | **注意:有时候遇到生产Bug需要发版时,可以通过第三段+1来发强制更新版本** 932 | 933 | 后两段最大大小自己按需求限制,如20,30 934 | 935 | 936 | #### 注释规范 937 | ##### 方法注释 938 | * 【推荐】每一个成员方法(自定义成员方法,覆盖方法,属性方法)的前面必须做好注释,默认是在方法前输入`/**+回车`即可出来。 939 | 也可以自定义模板注释: 940 | * 首先创建`Template Group...` 941 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5091684735764e83856a84aab6ad971c~tplv-k3u1fbpfcp-zoom-1.image) 942 | * 接着创建`Live Template` 943 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/222e73f207c84976827d2c15a9a439da~tplv-k3u1fbpfcp-zoom-1.image) 944 | * 在`Abbreviation` 输入快捷键,在`Template text`定义自己的注释 945 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7da6bbed773a47feb480989e925d4bd5~tplv-k3u1fbpfcp-zoom-1.image) 946 | * 因为模板里设置了日期时间,因此点击`Edit variables`需要给`date`和`time`赋值 947 | ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cf727a7834c14a1f9c2f5c8ffd29ce8d~tplv-k3u1fbpfcp-zoom-1.image) 948 | 949 | 设置完模板后,新建一个方法,在方法前输入`ann`+回车即可出现方法模板注释 950 | 951 | ``` 952 | /** 953 | * @Description:${todo} 954 | * @param ${tags} 955 | * @return ${return_type} 956 | * @author ${user} 957 | * @date 2021/9/2 15:08 958 | */ 959 | public WechatArticleAdapter(@Nullable List data){ 960 | super(R.layout.base_text_item,data); 961 | 962 | } 963 | ``` 964 | 965 | ##### 类全局变量注释规范 966 | * 【强制】类、类属性、类方法的注释必须使用javadoc规范,使用`/**内容*/`格式,不得使用`//xxx`方式和`/*xxx*/`方式。 967 | ``` 968 | /** 969 | * 文章url 970 | */ 971 | String mWebUrl = ""; 972 | 973 | ``` 974 | 975 | ##### 方法内注释规范 976 | * 【强制】方法内注释使用`//xxx注释`或者`/*xxx*/`,并且在代码前进行注释,不能再代码后面注释 977 | ``` 978 | //正例 979 | private void init() { 980 | //获取屏幕密度 981 | mDensity = getContext().getResources().getDisplayMetrics().density; 982 | } 983 | 984 | //反例 985 | private void init() { 986 | mDensity = getContext().getResources().getDisplayMetrics().density;//获取屏幕密度 987 | } 988 | ``` 989 | 990 | #### 代码样式规范 991 | * 【强制】代码之间应该有适当的空格,不能多也不能太少 992 | * 【推荐】左大括号不需要单独一行,与前面代码同一行并用空格隔开 993 | ``` 994 | //反例 995 | if (xxx) 996 | { 997 | } 998 | 999 | //正例 1000 | if (xxx) { 1001 | 1002 | } 1003 | ``` 1004 | 1005 | * 【强制】每个判断语句都需要加左右括号,即便是只有一句 1006 | ``` 1007 | //反例 1008 | if () xxxx 1009 | 1010 | //正例 1011 | if () { 1012 | xxxx 1013 | } 1014 | ``` 1015 | 1016 | ##### 代码换行规范 1017 | 1018 | * 【推荐】单行代码较长可以适当换行 1019 | ``` 1020 | // 反例 1021 | ScaleAnimation mScaleAnimation = new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 1022 | imageview.startAnimation(mScaleAnimation); 1023 | 1024 | //正例 1025 | ScaleAnimation mScaleAnimation = new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.1f, 1026 | Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 1027 | imageView.startAnimation(mScaleAnimation); 1028 | ``` 1029 | * 【推荐】当一个方法有很多参数的时候,应该在每个参数`,`换行 1030 | ``` 1031 | //反例 1032 | setArrowAnimate(mTopArticleAdapter, topArticleFootView.findViewById(R.id.home_iv_toparticlearrow), true,true); 1033 | 1034 | //正例 1035 | setArrowAnimate(mTopArticleAdapter, 1036 | topArticleFootView.findViewById(R.id.home_iv_toparticlearrow), 1037 | isShowOnlythree, 1038 | true, 1039 | true); 1040 | ``` 1041 | 1042 | * 【强制】当一行中调用多个函数时,每个函数单独一行,换行符在`.`之前 1043 | ``` 1044 | //反例 1045 | Glide.with(context).load(resourceId).transition(withCrossFade()).into(imageView); 1046 | 1047 | //正例 1048 | Glide.with(context) 1049 | .load(resourceId) 1050 | .transition(withCrossFade()) 1051 | .into(imageView); 1052 | ``` 1053 | 1054 | * 【推荐】方法参数排序可以按照重要程度进行排序 1055 | 1056 | ##### for循环规范 1057 | * 【推荐】在不需要使用下标的情况下,建议使用for_each循环 1058 | * 【强制】禁止在for循环的第二个条件中调用任何方法 1059 | ``` 1060 | //反例: 1061 | for(int i =0;i < array.length;i++) 1062 | 1063 | //正例 1064 | int size = array.length; 1065 | for(int i = 0; i< size;i++) 1066 | 1067 | //正例 1068 | for(init i = 0,n = array.length;i < n;i++) { 1069 | 1070 | } 1071 | 1072 | ``` 1073 | 1074 | * 【强制】异常处理写在循环外面,禁止写在循环内 1075 | ``` 1076 | //反例 1077 | for (int i = 0; i < 10; i++) { 1078 | try { 1079 | 1080 | } catch (Exception e) { 1081 | 1082 | } 1083 | } 1084 | 1085 | //正例 1086 | try { 1087 | for (int i = 0; i < 10; i++) { 1088 | } 1089 | } catch (Exception e) { 1090 | 1091 | } 1092 | 1093 | ``` 1094 | 1095 | * 【推荐】循环嵌套外小内大原则,多重循环把大循环放到内层 1096 | ``` 1097 | for (int i = 0;i < 10;i ++) { 1098 | //下面每次循环预测成功9999次 1099 | //这样的过程重复10次 1100 | for (int j = 0;j < 10000;j++) { 1101 | a[i][j]++; 1102 | } 1103 | } 1104 | 1105 | for (int j = 0;j < 10000;j++) { 1106 | //下面每次循环预测成功9次 1107 | //第一次没用预测,最后退出循环时预测失败1次 1108 | //这样的过程重复10000次 1109 | for (int i = 0;i < 10;i++) { 1110 | a[i][j]++; 1111 | } 1112 | } 1113 | 1114 | 1115 | ``` 1116 | 1117 | * 【推荐】循环内不要不断创建对象引用 1118 | ``` 1119 | //反例 1120 | for (int i = 1; i <= count; i++) 1121 | { 1122 | Object obj = new Object(); 1123 | } 1124 | 1125 | //正例 1126 | Object obj = null; 1127 | for (int i = 0; i <= count; i++) 1128 | { 1129 | obj = new Object(); 1130 | } 1131 | 1132 | ``` 1133 | 这样的话,内存中只有一份Object对象引用,每次new Object()的时候,Object对象引用指向不同的Object罢了,但是内存中只有一份,这样就大大节省了内存空间了。 1134 | 1135 | 1136 | ##### 类成员顺序规范 1137 | * 【推荐】类成员可以按照如下顺序 1138 | * 常量(Kotlin伴生对象要在开头) 1139 | * 字段(可以按执行顺序,重要程度) 1140 | * 构造函数 1141 | * 重写函数 1142 | * 共有函数 1143 | * 私有函数 1144 | * 内部类和接口 1145 | 1146 | `Activity`和`Fragment`如有多个生命周期重写函数,则按调用生命周期顺序来排序 1147 | 1148 | #### 依赖第三方库规范 1149 | * 【强制】每一行依赖库之前必须有注释,出自哪里 1150 | ``` 1151 | //正例 1152 | //全局加载视图框架 https://github.com/KingJA/LoadSir 1153 | implementation "com.kingja.loadsir:loadsir:$loadsirVersion" 1154 | 1155 | //反例 1156 | implementation "com.kingja.loadsir:loadsir:$loadsirVersion" 1157 | ``` 1158 | * 【强制】尽量使用一直维护的库,长时间不维护的(3年以上)需要慎重考虑 1159 | * 【强制】每个依赖库不能用`latest-version`,必须指定某个版本,因为有时候第三方库发布了最新版本,出现问题,而你又引用了,但是测试没测试,有可能漏到生产上 1160 | 1161 | * 【推荐】框架有问题时,及时联系库作者进行反馈 1162 | 1163 | #### 异常捕抓规范 1164 | * 【强制】不要使用`try catch`处理业务逻辑 1165 | * 【强制】不能为了减少`崩溃`而大量使用`try catch`,具体看需求看场景 1166 | * 【强制】不要在循环中使用`try catch`,应该把其放在最外层 1167 | * 【强制】必须捕获具体异常,不能用`Exception`来捕抓,并且在代码输出对应日志 1168 | ``` 1169 | //反例 1170 | try { 1171 | xxxx 1172 | } catch (Exception e) {} 1173 | 1174 | //正例 1175 | try { 1176 | xxxx 1177 | } catch (FileNotFoundException e) { 1178 | e.printStackTrace(); 1179 | //进行上报服务器处理 1180 | } catch (IOException e) { 1181 | e.printStackTrace(); 1182 | //进行上报服务器处理 1183 | } 1184 | 1185 | ``` 1186 | 1187 | * 【强制】不是有异常就要用`try catch`,不能通过捕获处理异常,可以通过一些逻辑判断避免进入一些异常 1188 | ``` 1189 | //反例 1190 | try { 1191 | Layout mNamelayout = getLayout(); 1192 | float mSpacingMult = mNamelayout.getSpacingMultiplier() 1193 | } catch (NullPointerException e) { 1194 | //当mNameLayout为空进来 1195 | } 1196 | 1197 | //正例 1198 | Layout mNamelayout = getLayout(); 1199 | if (mNamelayout == null) { 1200 | return; 1201 | } 1202 | float mSpacingMult = mNamelayout.getSpacingMultiplier() 1203 | ``` 1204 | 1205 | #### TODO规范 1206 | * 【推荐】记录想法,记录功能点,开发过程中可以利用`TODO`记录一下临时想法或为了不打扰思路留下待完善的说明 1207 | * 【推荐】删除无用`TODO`,开发工具自动生成的`TODO`,或则已经完善的`TODO`,一定要删除 1208 | 1209 | #### FIXME规范 1210 | * 【推荐】若代码存在严重问题或仅用于调试,使用FIXME加以标记 1211 | 1212 | #### so库命名规范 1213 | 如果自己开发`so`(lib包目录下`armeabi-v7a`,`arm64-v8a`下的so结尾)库,以`lib+模块+作用`命名方式,小写英文,如: 1214 | ``` 1215 | liblivevideo.so 1216 | libchat.so 1217 | libmessageflutter.so 1218 | ``` 1219 | 1220 | #### jar包命名规范 1221 | 当APP有用到`jar`包,以`模块+作用+b版本号`命名方式,中间以`_`隔开,禁止英文拼音结合,如: 1222 | ``` 1223 | wechatzxing_1.0.0.jar 1224 | squareshare_1.0.0.jar 1225 | messagedownload_1.0.0.jar 1226 | ``` 1227 | 1228 | #### kotlin规范 1229 | ##### kotlin基本规范 1230 | * 在 Kotlin 中,分号是可选的,因此换行很重要,每句语句后都必须使用一个换行,不使用分号 1231 | * 不在`.`、`?.`、`::`左右留空格 1232 | * 二元条件优先使用`if`而不是`when`,如果有三个或多个选项优先使用`when` 1233 | ``` 1234 | //反例 1235 | when (x) { 1236 | null -> // …… 1237 | else -> // …… 1238 | } 1239 | 1240 | //正例 1241 | if (x == null) ....else.... 1242 | ``` 1243 | * 如果需要在条件语句中用到可空的`Boolean`, 使用`if (value == true)`或`if (value == false)`检测 1244 | * 当一个方法接受多个相同的原生类型参数带有参数默认值时,请使用具名参数语法, 除非在上下文中的所有参数的含义都已绝对清楚 1245 | ``` 1246 | fun getOvalAreal(x:Int = 20,y:Int = 10,width:Int,height:Int,fill:Boolean = false):{ 1247 | } 1248 | 1249 | getOvalAreal(x = 10, y = 10, width = 100, height = 100, fill = true) 1250 | 1251 | ``` 1252 | * 少写重载方法,多用具名函数,函数在重写的时候注意形参的参数名要一致 1253 | * 不要在主构造函数声明、方法声明或者方法调用的左括号之前留空格 1254 | ``` 1255 | class A(val x: Int) 1256 | fun foo(x: Int) { …… } 1257 | fun bar() { 1258 | foo(1) 1259 | } 1260 | ``` 1261 | * 不要在用于标记可空类型的`?`前留空格:`String?` 1262 | * 在较长参数列表的左括号后添加一个换行符,按 4 个空格缩进参数,将密切相关的多个参数分在同一行,分隔参数名与值的 `=` 左右留空格 1263 | ``` 1264 | drawSquare( 1265 | x = 10, y = 10, 1266 | width = 100, height = 100, 1267 | fill = true 1268 | ) 1269 | ``` 1270 | * 当对链式调用换行时,将`.`字符或者`?.`操作符放在下一行,并带有缩进 1271 | ``` 1272 | val anchor = owner 1273 | ?.firstChild!! 1274 | .siblings(forward = true) 1275 | .dropWhile { it is PsiComment || it is PsiWhiteSpace } 1276 | ``` 1277 | * 常量用`const`修饰(用`@JvmField`也可以),`const`必须修饰`val`,不要以为用`val`修饰就是常量,如下面`currentTimeMillis`不是常量,因为每次访问`currentTimeMillis`都会改变 1278 | ``` 1279 | //这不是常量 1280 | val currentTimeMillis: Long 1281 | get() { return System.currentTimeMillis() } 1282 | 1283 | ``` 1284 | * 需要遍历数组时,优先使用`withIndex`和`indices`方式,这两种方式不会创建额外对象,而`forEach`,区间表达式和`step`这两种方式会创建额外对象 1285 | ``` 1286 | for (index in array.indices) { 1287 | 1288 | } 1289 | for ((index, value) in array.withIndex()) { 1290 | 1291 | } 1292 | ``` 1293 | 1294 | * 尽量少用`toLowerCase`和`toUpperCase`方法,因为这两种方法会创建一个新的字符串出来进行比较,可以使用`equals`来代替并添加可选参数`ignoreCase`来忽略大小写 1295 | ``` 1296 | xxx.equals(ssss,ignoreCase = true) 1297 | ``` 1298 | * 尽量不要使用`lateinit`来定义不可空类型的变量,可能会在使用时出现null的情况 1299 | * 读变量可以使用`by lazy { }`实现懒加载,并根据场合设置线程安全类型,UI线程建议设置为NONE 1300 | * `LazyThreadSafetyMode.NONE` 仅仅在单线程 1301 | * `LazyThreadSafetyMode.SYNCHRONIZED`在多线程中使用 1302 | * `LazyThreadSafetyMode.PUBLICATION`不常用 1303 | 1304 | 1305 | ``` 1306 | private val lazyImmutableValue: String by lazy { 1307 | "Hello" 1308 | } 1309 | 1310 | private val lazyImmutableValueNoThreadSafe: String by lazy(LazyThreadSafetyMode.NONE) { 1311 | "Hello" 1312 | } 1313 | 1314 | ``` 1315 | * 纯工具静态方法的使用,在类里的`companion object`中定义,会有额外开销,如不得不在伴生对象中实现静态方法,请添加`@JvmStatic`注解 1316 | ``` 1317 | // 推荐 1318 | // SimpleClass.kt 1319 | fun myUtilMethod() { 1320 | // Some things 1321 | } 1322 | 1323 | // 不推荐 1324 | // SimpleClass.kt 1325 | class SimpleClass { 1326 | companion object { 1327 | fun myUtilMethod() { 1328 | } 1329 | } 1330 | } 1331 | 1332 | // 禁止 1333 | // SimpleClass.kt 1334 | object SimpleClass { 1335 | fun myUtilMethod() { 1336 | } 1337 | } 1338 | 1339 | ``` 1340 | 1341 | 1342 | 1343 | 1344 | ##### 声明规范 1345 | * 【强制】如果是可变变量,请用`var`修饰,如果是只读变量,请用`val`修饰 1346 | * 可变变量:可以进行修改 1347 | * 只读变量:当初始化一次后不能被二次改变 1348 | 1349 | * 【推荐】可见性方法修饰符除`public`外必须明确写出来(`kotlin`默认是public) 1350 | ``` 1351 | //反例 1352 | fun startPreview() 1353 | //正例 1354 | private fun startPreview() 1355 | ``` 1356 | 1357 | ##### 源文件名称规范 1358 | 如果 Kotlin 文件包含单个类(以及可能相关的顶层声明),那么文件名应该与该类的名称相同,并追加`.kt`扩展名。如果文件包含多个类或只包含顶层声明, 那么选择一个描述该文件所包含内容的名称,并以此命名该文件。 使用首字母大写的驼峰风格(也称为 Pascal 风格), 例如`ProcessDeclarations.kt` 1359 | 1360 | ##### 类头排版规范 1361 | * 【推荐】有少数主构造函数参数的类可以写成一行 1362 | ``` 1363 | class Person(id: Int, name: String) 1364 | ``` 1365 | * 【推荐】具有较长的类头的类进行格式化,每个函数参数占一行 1366 | ``` 1367 | class Person( 1368 | id: Int, 1369 | name: String, 1370 | surname: String 1371 | ) : Human(id, name) { /*……*/ } 1372 | ``` 1373 | * 【推荐】对于多个接口,应该将超类构造函数调用放在首位,然后将每个接口应放在不同的行中 1374 | ``` 1375 | class Person( 1376 | id: Int, 1377 | name: String, 1378 | surname: String 1379 | ) : Human(id, name), 1380 | KotlinMaker { /*……*/ } 1381 | ``` 1382 | ##### 格式化控制流语句规范 1383 | * 【推荐】在`when`语句中,如果一个分支不止一行,可以考虑用空行将其与相邻的分支块分开 1384 | ``` 1385 | private fun parsePropertyValue(propName: String, token: Token) { 1386 | when (token) { 1387 | is Token.ValueToken -> 1388 | callback.visitValue(propName, token.value) 1389 | //空一行 1390 | Token.LBRACE -> { // …… 1391 | } 1392 | } 1393 | } 1394 | ``` 1395 | 1396 | * 【推荐】在`when`语句中和`if`语句中,如果有短分支(单行),将短分支放在与条件相同的行上,无需花括号 1397 | ``` 1398 | when (foo) { 1399 | true -> bar() // 正例 1400 | false -> { baz() } // 反例 1401 | } 1402 | 1403 | if (string.isEmpty()) return 1404 | val value = if (a == b) 0 else 1 1405 | ``` 1406 | 1407 | #### 代码提交规范 1408 | * 【强制】每天上班前先更新代码 1409 | * 【推荐】工作目录要及时更新,不要和服务起有太大的差别 1410 | * 【强制】提交代码时,如果出现冲突,先仔细分析解决,不可以强行提交 1411 | * 【强制】提交代码之前先在本地进行测试,确保项目能编译通过,且能够正常运行,不可盲目提交 1412 | * 【强制】必须保证服务器上的版本是正确的,项目有错误时,不要进行提交 1413 | * 【强制】提交之前先更新 1414 | * 【强制】提交时注意不要提交本地自动生成的文件,如`idea`,`build`文件夹是不需要提交的 1415 | * 【推荐】不要提交自己不明白的代码 1416 | * 【推荐】对提交的信息采用明晰详细的标注(如改了什么...) 1417 | 1418 | #### 日常开发规则 1419 | * 以接口兼容为荣,以接口裸奔为耻 1420 | * 以规范日志为荣,以乱打日志为耻 1421 | * 以代码自测为荣,以过度自信为耻 1422 | * 以参数校验为荣,以过度自信为耻 1423 | * 以设计模式为荣,以代码重复为耻 1424 | * 以优化代码为荣,以复制粘贴为耻 1425 | * 以定义常量为荣,以魔法数字为耻 1426 | * 以总结思考为荣,以浑水摸鱼为耻 1427 | * 以多敲代码为荣,以懒散懈怠为耻 1428 | * 以高度负责为荣,以搪塞敷衍为耻 1429 | 1430 | #### 参考文章 1431 | * [https://github.com/getActivity/AndroidCodeStandard](https://github.com/getActivity/AndroidCodeStandard) 1432 | * [https://mp.weixin.qq.com/s/IOR1911jtyQfeUOKIwEUwA](https://mp.weixin.qq.com/s/IOR1911jtyQfeUOKIwEUwA) 1433 | * [https://google.github.io/styleguide/javaguide.html](https://google.github.io/styleguide/javaguide.html) 1434 | * [https://github.com/android/architecture-samples](https://github.com/android/architecture-samples) 1435 | * [https://source.android.com/source/code-style](https://source.android.com/source/code-style) 1436 | * [https://github.com/QinGuiCheng/AndroidStandardDevelop](https://github.com/QinGuiCheng/AndroidStandardDevelop) 1437 | * [https://www.cnblogs.com/myseries/p/10694246.html](https://www.cnblogs.com/myseries/p/10694246.html) 1438 | * [https://www.kotlincn.net/docs/reference/control-flow.html](https://www.kotlincn.net/docs/reference/control-flow.html) 1439 | * 阿里巴巴Android开发规范 1440 | 1441 | #### 最后 1442 | * 好的规范能够提高代码质量,使得新人加入项目的时候降低理解代码的难度 1443 | * 规矩规范终究是死的,适合团队的才是最好的 1444 | * 规范需要团队一起齐心协力来维护执行,在团队生活里,谁都不可能独善其身 1445 | * 一开始可能会有些不习惯,持之以恒,总会成功的 1446 | 1447 | 1448 | 如有更好的规范、其他建议、本规范错误地方,欢迎提`issue`。 1449 | 1450 | 1451 | ## License 1452 | 1453 | ```text 1454 | Copyright 2021 Knight 1455 | 1456 | Licensed under the Apache License, Version 2.0 (the "License"); 1457 | you may not use this file except in compliance with the License. 1458 | You may obtain a copy of the License at 1459 | 1460 | http://www.apache.org/licenses/LICENSE-2.0 1461 | 1462 | Unless required by applicable law or agreed to in writing, software 1463 | distributed under the License is distributed on an "AS IS" BASIS, 1464 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1465 | See the License for the specific language governing permissions and 1466 | limitations under the License. 1467 | ``` 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | --------------------------------------------------------------------------------