前言
- 好的命名规则能够提高代码质量,使得新人加入项目的时候降低理解代码的难度;
- 规矩终究是死的,适合团队的才是最好的;
- 命名规范需要团队一起齐心协力来维护执行,在团队生活里,谁都不可能独善其身;
- 一开始可能会有些不习惯,持之以恒,总会成功的。
制定好了规范,就要遵守,有了统一的规范,项目才好维护,相互之间才好review代码,便于开发与维护。
一、编程规范
(一)命名风格
1、类命名: 命名用大驼峰命名法,每一个单词的首字母都大写
类 | 描述 | 例如 |
---|---|---|
Activity 类 | Activity 为后缀标识 | 登录类 LoginActivity |
Adapter 类 | Adapter 为后缀标识 | 聊天适配器 ChatAdapter |
解析类 | Parser 为后缀标识 | 首页解析类 HomePosterParser |
工具方法类 | Utils 或 Manager 为后缀标识 | 线程池管理类:ThreadPoolManager 日志工具类: LogUtils 打印工具类: PrinterUtils |
数据库类 | 以 DBHelper 后缀标识 | 信息流数据库:MomentsDBHelper |
Service 类 | 以 Service 为后缀标识 | 时间服务 TimeService |
BroadcastReceiver 类 | 以 Receiver 为后缀标识 | 推送接收 JPushReceiver |
ContentProvider 类 | 以 Provider 为后缀标识 | ShareProvider |
自定义的共享基础类 | 以 Base 开头 | BaseActivity , BaseFragment |
测试类 | 以Test 为后缀标识 | MomentsTest |
2、常量命名:全部字母大写,用下划线分隔单词
如:HT_DB_VERSION
Android SDK 中的很多类都用到了键值对函数,比如 SharedPreferences
、Bundle
、Intent
,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。
当时用到这些类的时候,我们 必须 将它们的键定义为 static final
字段,并遵循以下指示作为前缀。
类 | 字段名前缀 |
---|---|
SharedPreferences | PREF_ |
Bundle | BUNDLE_ |
Fragment Arguments | ARGUMENT_ |
Intent Extra | EXTRA_ |
Intent Action | ACTION_ |
说明:虽然 Fragment.getArguments()
得到的也是 Bundle
,但因为这是 Bundle
的常用用法,所以特意为此定义一个不同的前缀。
例如:
// 注意:字段的值与名称相同以避免重复问题
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";
// 与意图相关的项使用完整的包名作为值的前缀
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";
3、非常量字段名:命名用小驼峰命名法,第一个单词的首字母小写,后面的单词的首字母全部大写
分类 | 描述 | 例如 | |
---|---|---|---|
成员变量 | 非公有,非静态字段命名以 静态字段命名以 公有字段命名以public开头。 其他字段以小写字母开头。 boolean命名以**开头。(待讨论) |
| |
局部变量 | 用小驼峰命名法以小写字母开头即可,但尽量避免用单个字符命名 | mainTitle | |
临时变量 | 临时变量通常被取名为 | for (int i = 0; i < len; i++) | |
控件类型 | Android 众多的 UI 控件,为避免控件和普通成员变量混淆以及更好地表达意思,所有用来表示控件的成员变量统一加上控件缩写作为前缀。详见UI 控件缩写表 | mIvAvatar、rvBooks、flContainer
| |
数据类型 | 对于表示集合或者数组的非常量字段名,我们可以添加后缀来增强字段的可读性,比如: 集合添加如下后缀:List、Map、Set。 数组添加如下后缀:Arr。 | mIvAvatarList 、userArr 、firstNameSet | |
量词 | 变量名中可能会出现量词,我们需要创建统一的量词,它们更容易理解,也更容易搜索,比如: First: 一组变量中的第一个 | mFirstBook 、mPreBook 、curBook |
UI 控件缩写表
名称 | 缩写 |
---|---|
Button | btn |
CheckBox | cb |
EditText | et |
FrameLayout | fl |
GridView | gv |
ImageButton | ib |
ImageView | iv |
LinearLayout | ll |
ListView | lv |
ProgressBar | pb |
RadioButtion | rb |
RecyclerView | rv |
RelativeLayout | rl |
ScrollView | sv |
SeekBar | sb |
Spinner | spn |
TextView | tv |
ToggleButton | tb |
VideoView | vv |
WebView | wv |
3、方法命名:命名用小驼峰命名法
方法名通常是动词或动词短语。
方法 | 说明 |
---|---|
initXX() | 初始化相关方法,使用 init 为前缀标识,如初始化布局 initView() |
isXX() , checkXX() | 方法返回值为 boolean 型的请使用 is/check 为前缀标识 |
getXX() | 返回某个值的方法,使用 get 为前缀标识 |
setXX() | 设置某个属性值 |
handleXX() , processXX() | 对数据进行处理的方法 |
displayXX() , showXX() | 弹出提示框和提示信息,使用 display/show 为前缀标识 |
updateXX() | 更新数据 |
saveXX() , insertXX() | 保存或插入数据 |
resetXX() | 重置数据 |
clearXX() | 清除数据 |
removeXX() , deleteXX() | 移除数据或者视图等,如 removeView() |
drawXX() | 绘制数据或效果相关的,使用 draw 前缀标识 |
4、自定义View命名:命名用大驼峰命名法
如:xxxView,xxxLayout
5、布局文件命名(layout/)
布局文件分别要以activity_,fragment_,layout_ ,item_ 等开头。
命名规则:类型_模块名
、类型{_模块名}_逻辑名称
。
说明:{}
中的内容为可选。
例如:
名称 | 说明 |
---|---|
activity_main.xml | 主窗体 类型_模块名 |
activity_main_head.xml | 主窗体头部 类型_模块名_逻辑名称 |
fragment_music.xml | 音乐片段 类型_模块名 |
fragment_music_player.xml | 音乐片段的播放器 类型_模块名_逻辑名称 |
dialog_loading.xml | 加载对话框 类型_逻辑名称 |
ppw_info.xml | 信息弹窗(PopupWindow) 类型_逻辑名称 |
item_main_song.xml | 主页歌曲列表项 类型_模块名_逻辑名称 |
6、Drawable命名
要一眼能看出它的作用,比如:shape_shadow_bottom.xml,selected_indicator_red.xml,
第一个,看命名就知道它是一个shape,它是一个阴影,并且位置在下面。
第二个,一看就知道他是一个selected,作用在指示线,颜色是红的。
如果不这样命名,drawable是非常容易出现大量重复作用的文件。
7、图片命名(drawable/ 和 mipmap/)
res/drawable/
目录下放的是位图文件(.png、.9.png、.jpg、.gif)或编译为可绘制对象资源子类型的 XML 文件,而 res/mipmap/
目录下放的是不同密度的启动图标,所以 res/mipmap/
只用于存放启动图标,其余图片资源文件都应该放到 res/drawable/
目录下。
命名规则:类型{_模块名}_逻辑名称
、类型{_模块名}_颜色
。
说明:{}
中的内容为可选;类型
可以是可绘制对象资源类型,也可以是控件类型(具体见附录UI 控件缩写表);最后可加后缀 _small
表示小图,_big
表示大图。
例如:
名称 | 说明 |
---|---|
btn_main_about.png | 主页关于按键 类型_模块名_逻辑名称 |
btn_back.png | 返回按键 类型_逻辑名称 |
divider_maket_white.png | 商城白色分割线 类型_模块名_颜色 |
ic_edit.png | 编辑图标 类型_逻辑名称 |
bg_main.png | 主页背景 类型_逻辑名称 |
btn_red.png | 红色按键 类型_颜色 |
btn_red_big.png | 红色大按键 类型_颜色 |
ic_head_small.png | 小头像图标 类型_逻辑名称 |
bg_input.png | 输入框背景 类型_逻辑名称 |
divider_white.png | 白色分割线 类型_颜色 |
bg_main_head.png | 主页头部背景 类型_模块名_逻辑名称 |
def_search_cell.png | 搜索页面默认单元图片 类型_模块名_逻辑名称 |
ic_more_help.png | 更多帮助图标 类型_逻辑名称 |
divider_list_line.png | 列表分割线 类型_逻辑名称 |
sel_search_ok.xml | 搜索界面确认选择器 类型_模块名_逻辑名称 |
shape_music_ring.xml | 音乐界面环形形状 类型_模块名_逻辑名称 |
如果有多种形态,如按钮选择器:sel_btn_xx.xml
,采用如下命名:
名称 | 说明 |
---|---|
sel_btn_xx | 作用在 btn_xx 上的 selector |
btn_xx_normal | 默认状态效果 |
btn_xx_pressed | state_pressed 点击效果 |
btn_xx_focused | state_focused 聚焦效果 |
btn_xx_disabled | state_enabled 不可用效果 |
btn_xx_checked | state_checked 选中效果 |
btn_xx_selected | state_selected 选中效果 |
btn_xx_hovered | state_hovered 悬停效果 |
btn_xx_checkable | state_checkable 可选效果 |
btn_xx_activated | state_activated 激活效果 |
btn_xx_window_focused | state_window_focused 窗口聚焦效果 |
注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector,前提是命名要规范。
8、菜单资源文件(menu/)
菜单相关的资源文件应放在该目录下。
命名规则:menu{_模块名}_逻辑名称
说明:{}
中的内容为可选。
例如:menu_main_drawer.xml
、menu_navigation.xml
。
9、values资源文件(values/)
待定
10、动画资源文件(anim/ 和 animator/)
安卓主要包含属性动画和视图动画,其视图动画包括补间动画和逐帧动画。
属性动画文件需要放在 res/animator/
目录下,
视图动画文件需放在 res/anim/
目录下。
命名规则:anim_{模块名_}逻辑名称
。
说明:{}
中的内容为可选,逻辑名称
可由多个单词加下划线组成。
例如:anim_refresh_progress.xml
、anim_market_cart_add.xml
、anim_market_cart_remove.xml
。
如果是普通的补间动画或者属性动画,可采用:动画类型_方向
的命名方式。
例如:
名称 | 说明 |
---|---|
fade_in | 淡入 |
fade_out | 淡出 |
push_down_in | 从下方推入 |
push_down_out | 从下方推出 |
push_left | 推向左方 |
slide_in_from_top | 从头部滑动进入 |
zoom_enter | 变形进入 |
slide_in | 滑动进入 |
shrink_to_middle | 中间缩小 |
11、颜色资源文件(color/)
专门存放颜色相关的资源文件。
命名规则:类型{_模块名}_逻辑名称
。
说明:{}
中的内容为可选。
例如:sel_btn_font.xml
。
颜色资源也可以放于 res/drawable/
目录,引用时则用 @drawable
来引用,但不推荐这么做,最好还是把两者分开
12、id 命名
命名规则:view 缩写{_模块名}_逻辑名
,例如: btn_main_search
、btn_back
。
如果在项目中有用黄油刀的话,使用 AS 的插件:ButterKnife Zelezny,可以非常方便帮助你生成注解;没用黄油刀的话可以使用 Android Code Generator 插件。
13、其它
1、插件检测(以该插件提示为准,警告的都修改过来)
请自行安装《阿里巴巴Java开发规约》插件,在(Preferences > Plugins)插件处搜索alibaba即可。
2、开发时新功能完全依照《阿里巴巴Java开发规约》提示,老功能的话开发到的地方根据提示尽量修改过来,review时作为review通过标准之一。
(二)常量定义
代码中不要出现数字常量,如果有数字常量判断的话,需要定义出来,并增加注释说明含义
(三)代码格式
1、代码格式化后再上传
2、代码不要出现数字
3、接口参数或定义的常量或请求的URL等,一定要增加注释说明。即达到离开了文档也能明白这个接口是干什么的,每一个参数含义用法等,返回的参数同样。
4、if条件判断,如果只有一行代码的,请加上{},方便阅读。如果一定不想加{},请使用这种形式:if (condition) body();
5、编写简短方法:在可行的情况下,尽量编写短小精炼的方法。我们了解,有些情况下较长的方法是恰当的,因此对方法的代码长度没有做出硬性限制。如果某个方法的代码超出 40 行,请考虑是否可以在不破坏程序结构的前提下对其拆解。
6、类的成员顺序:这并没有唯一的正确解决方案,但如果都使用一致的顺序将会提高代码的可读性,推荐使用如下排序:
- 常量
- 字段
- 构造函数
- 重写函数和回调
- 公有函数
- 私有函数
- 内部类或接口
如果类继承于 Android 组件(例如 Activity
或 Fragment
),那么把重写函数按照他们的生命周期进行排序。
7、函数参数的排序:在 Android 开发过程中,Context
在函数参数中是再常见不过的了,我们最好把 Context
作为其第一个参数。
正相反,我们把回调接口应该作为其最后一个参数。如:public void loadUserAsync(Context context, int userId, UserCallback callback);
8、代码块和layout推荐可用块注释把代码分类开来
9、在循环中或多层级对象时,如果获取某个对象的多个某值时,把对象定义出来,再获取
如:
|
|
(四)注释风格
为了减少他人阅读你代码的痛苦值,请在关键地方做好注释。
类、方法、字段等都需要根据情况增加注释,个别容易理解的可不加。
1、类注释
每个类完成后应该有作者姓名和创建时间的注释,对自己的代码负责。
具体可以在 AS 中自己配制,进入 Preferences -> Editor -> File and Code Templates -> Includes -> File Header,输入模板
/**
* Created by ${USER} on ${YEAR}/${MONTH}/${DAY}.
* 请写类注释
*/
这样便可在每次新建类的时候自动加上该头注释。
2、方法注释
每一个成员方法(包括自定义成员方法、覆盖方法、属性方法)的方法头都必须做方法头注释,在方法前一行输入 /** + 回车
或者设置 Fix doc comment
(Preferences -> Keymap -> Fix doc comment)快捷键,AS 便会帮你生成模板,我们只需要补全参数即可
3、块注释
块注释与其周围的代码在同一缩进级别。它们可以是 /* ... */
风格,也可以是 // ...
风格(//
后最好带一个空格)。
对于多行的 /* ... */
注释,后续行必须从 *
开始, 并且与前一行的 *
对齐。
以下示例注释都是 OK 的。
|
4、其它一些注释
AS 已帮你集成了一些注释模板,我们只需要直接使用即可,在代码中输入 todo
、fixme
等这些注释模板,回车后便会出现如下注释。
// TODO: 2019/2/23 需要实现,但目前还未实现的功能的说明
// FIXME: 2019/2/23 需要修正,甚至代码是错误的,不能工作,需要修复的说明
(五)包
1、包名全部小写,连续的单词只是简单地连接起来,不使用下划线,采用反域名命名规则,全部使用小写字母
一级包名是顶级域名,通常为 com
、edu
、gov
、net
、org
等,
二级包名为公司名,
三级包名根据应用进行命名,后面就是对包名的划分了。
2、包分类以及MVP风格
(六)、其它的一些规范
-
合理布局,有效运用
<merge>
、<ViewStub>
、<include>
标签; -
Activity
和Fragment
里面有许多重复的操作以及操作步骤,所以我们都需要提供一个BaseActivity
和BaseFragment
,让所有的Activity
和Fragment
都继承这个基类。 -
方法基本上都按照调用的先后顺序在各自区块中排列;
-
相关功能作为小区块放在一起(或者封装掉);
-
当一个类有多个构造函数,或是多个同名函数,这些函数应该按顺序出现在一起,中间不要放进其它函数;
-
数据提供统一的入口。无论是在 MVP、MVC 还是 MVVM 中,提供一个统一的数据入口,都可以让代码变得更加易于维护。比如可使用一个
DataManager
,把http
、preference
、eventpost
、database
都放在DataManager
里面进行操作,我们只需要与DataManager
打交道; -
多用组合,少用继承;
-
提取方法,去除重复代码。对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。
-
可引入
Dagger2
减少模块之间的耦合性。Dagger2
是一个依赖注入框架,使用代码自动生成创建依赖关系需要的代码。减少很多模板化的代码,更易于测试,降低耦合,创建可复用可互换的模块; -
项目引入
RxAndroid
响应式编程,可以极大的减少逻辑代码; -
通过引入事件总线,如:
EventBus
、AndroidEventBus
、RxBus
,它允许我们在DataLayer
中发送事件,以便ViewLayer
中的多个组件都能够订阅到这些事件,减少回调; -
尽可能使用局部变量;
-
及时关闭流;
-
尽量减少对变量的重复计算;
如下面的操作:
for
(
int
i =
0
; i < list.size(); i++) {
...
}
建议替换为:
for
(
int
i =
0
, len = list.size(); i < len; i++) {
...
}
-
尽量采用懒加载的策略,即在需要的时候才创建;
例如:String str =
"aaa"
;
if
(i ==
1
) {
}
建议替换为:
if
(i ==
1
) {
String str =
"aaa"
;
}
-
不要在循环中使用
try…catch…
,应该把其放在最外层; -
使用带缓冲的输入输出流进行 IO 操作;
-
尽量使用
HashMap
、ArrayList
、StringBuilder
,除非线程安全需要,否则不推荐使用HashTable
、Vector
、StringBuffer
,后三者由于使用同步机制而导致了性能开销; -
尽量在合适的场合使用单例;
使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:
-
控制资源的使用,通过线程同步来控制资源的并发访问。
-
控制实例的产生,以达到节约资源的目的。
-
控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。
-
-
把一个基本数据类型转为字符串,
基本数据类型.toString()
是最快的方式,String.valueOf(数据)
次之,数据 + ""
最慢; -
使用 AS 自带的 Lint 来优化代码结构(什么,你不会?右键 module、目录或者文件,选择 Analyze -> Inspect Code);
-
最后不要忘了内存泄漏的检测;
- 禁止直接打印PB对象,打印自定义的model时,需要在对应的model自己实现toString方法,不允许打印无意义model。
- 单例写法推荐:(待完善)
二、日志添加规范
目前我们的线上日志等级E的会记录到本地文件,为了大家都能一眼看懂输出的日志,需要遵循以下规范。
统一使用HT_Log.java
(一)、开发环境
HT_Log.v(),HT_Log.i(),HT_Log.w(),HT_Log.d(),HT_Log.e() 都会打印并记录到本地文件
(二)、线上环境
HT_Log.e()会打印并记录到本地文件
(三)、打印输出规范
1、每个类定义一个TAG,以当前类名为内容,当作log的tag,用来区分打印是来自哪个类(可在类模板里配置)
2、Log打印内容体组成规则:方法名_逻辑名_{_参数字段名}_具体要打印的参数值(多参数时以,号分隔开)
三、Git使用规范
1、上传先首先在本地编译,看代码是否能编译通过,保证其它成员拉到的代码是可正常运行的。
2、提交前一定前先review一遍自己修改到的每一个文件,每一行代码。看是否有错改、多改的地方。
3、log内容提交规范:动作描述_模块描述_功能描述_具体修改的地方或逻辑 (如:修改信息流列表接口逻辑)
动作描述 | 说明 |
---|---|
修改 | 修改代码或文件 |
添加 | 添加代码或文件 |
删除 | 删除代码或文件 |
4、勤更新、勤提交。
5、如在合并代码时,遇到文件冲突,如不能很正确的解决冲突点,可通过查看多版本代码比较确定差异点或找到开发当事人一起合并,防止把别人有效代码给覆盖。
四、数据上报规范
待讨论
1、数据上报逻辑代码是否可与功能逻辑代码分离,方便阅读以及以后增删维护。
五、第三方库或大型工具类代码引入规范
主要目的是为了减少重复引入或选型错误问题
引入第三方库或大型工具类代码最好由Leader统一选型后引入
如必须要亲自引入的,也需要组内知会一下所有成员(可通过企业微信群)
六、AS规范
1、尽量使用最新的稳定版的 IDE 进行开发,最好大家统一一个版本,一起升级;
2、编码格式统一为 UTF-8;
3、编辑完 .java、.xml 等文件后一定要格式化;
4、删除多余的 import,减少警告出现;
七、代码模板
待定