An Android Code Standard Document, It’s A Public Resource, You Might Find It On My Company’s Home Site Or Not.
1.避免坏习惯
1.1 代码重复几乎是最常见的坏习惯
代码重复往往来自于copy-and-paste的编程风格。
1.2 代码很长的方法
一个方法应当具有自我独立的意图,不要把几个意图放在一起。
1.3 大类
就是把太多的责任交给一个类,应该是一个类一个责任,这个和长方法相似。
1.4 一起出现在很多类的成员变量中,一起出现在许多方法的参数中…
这些数据或许应该自己独立形成对象。
1.5 一个干活不多的类
类的维护需要额外的开销,如果一个类承担了太少的责任,应当消除它。
1.6 一个类实现了从未用到的功能和通用性
通常这样的类或方法唯一的用户是testcase。不要犹豫,删除它。
1.7 一个对象的属性可能只在某些情况下才有意义
这样的代码将难以理解。专门建立一个对象来持有这样的孤儿属性,把只和他相关的行为移到该类。最常见的是一个特定的算法需要某些只有该算法才有用的变量。
1.8 做相同事情的方法有不同的函数
一致把它们往类层次上移,直至协议一致。
1.9 对象包括状态和行为
如果一个类只有状态没有行为,那么肯定有什么地方出问题了。
1.10 经常觉得要写很多注释才能解释你的代码
如果这种感觉太多,表示你需要重构。
2.命名规范
2.1 包命名
- 范围:
适用于包(package)的命名
- 命名规范:
一个唯一包名的前缀总是全部小写的 ASCII 字母并且是一个顶级域名,通常是 com,edu,gov,mil,net,org。
Ø 例如:
顶级域名.公司名.项目名.*(模块)
com.hengtiansoft.mobiledemo.
2.2 类和接口命名
- 范围:
适用于类(class)和接口(interface)的命名
- 命名规范:
类名是个一名词,采用大小写混合的方式,每个单词的首字母大写。类名应简洁而富于描述。使用完整单词,避免缩写词(除非该缩写词被更广泛使用,像 URL,HTML),接口一般要使用able、ible、er等后缀。
Ø 例如:
classUserHomeActivity
classIOUtils
interfaceUserClickListener
规约:类名必须使用驼峰规则,即首字母必须大写,如果为词组,则每个单词的首字母也必须要大写,类名必须使用名字,或名词词组。要求类名简单,不允许出现无意义的单词(如classXXXActivity)。
2.3 异常命名
- 范围:
适用于自定义异常(Exception)的命名
- 命名规范:
自定义异常的命名必须以Exception为结尾。
Ø 例如:
NetworkException
AppException
2.4 方法命名
- 范围:
适用于方法(method)的命名
- 命名规范:
方法名是一个动词,采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写。
类的获取方法(一般具有返回值)一般要求在被访问的字段名前加上get,如getFirstName (),getLastName()。
类的设置方法(一般返回类型为void):被访问字段名的前面加上前缀 set,如setFirstName(),setLastName()。
类的布尔型的判断方法一般要求方法名使用单词is做前缀,如isNetWorkConnected(),isString()。
类的普通方法一般采用完整的英文描述说明成员方法功能,第一个单词尽可能采用动词,首字母小写,如openFile(),addCount()。
构造方法应该用递增的方式写。(参数多的写在后面)
Ø 例如:
publicintgetId()
private void doBack()
2.5 变量命名
- 范围:
适用于Java代码中。在模型(model)或者bean对象中,成员变量命名可不遵循下述规范,直接使用小写字母开头。
- 命名规范:
第一个单词的首字母小写,其后单词的首字母大写。
非公有,非静态的变量以 m开头。
静态变量以s开头。
其他变量以小写字母开头。
公有静态最终(public static final)变量全大写并用下划线“_”分隔。
Ø 例如:
public class MyClass {
public static final int SOME_CONSTANT = 42;
publicintpublicField;
private static MyClasssSingleton;
intmPackagePrivate;
privateintmPrivate;
protectedintmProtected;
}
2.6 Android控件变量命名
- 范围:
适用于Java代码的Android控件命名。
- 命名规范:
[控件缩写_描述]
//首先应满足上述的变量命名规范。
Ø 例如:
private Button mBtnLogin
privateLinearLayoutmLlytMainContainer
publicAlertDialogalertConfirm;
2.7 Layout命名
2.7.1 Layout文件命名
- 范围:
应用于在res/layout目录下的文件。
- 命名规范:
[类型_描述]
类型:使用该文件的对象的类型,如果需要多个单词则直接合并,不使用“_”分隔
描述:描述该文件的功能,使用“-”分隔每个单词
layout xml的命名必须以 全部单词小写,单词间以”_”分割,并且使用名词或名词词组,即使用 模块名功能名称 来命名。
Ø 例如:
activity\_main.xml
fragment\_title.xml
dialog\_cancel\_confirm.xml
listitem\_game.xml
popup\_user\_info.xml
2.7.2 Layout文件中的id命名
- 范围:
应用于在res/layout目录下的文件中的id命名。
- 命名规范:
[控件缩写_描述]
控件缩写:该id所表示的控件的缩写
描述:描述该文件的功能,使用“_”分隔每个单词
layout中所使用的id必须以全部单词小写,单词间以下划线分割,并且使用名词或名词词组,并且要求能够通过id直接理解当前组件要实现的功能。
Ø 例如:
@+id/tv\_name
@+id/et\_first\_name
@+id/llyt\_user\_info
资源命名
规约:layout中所使用的所有资源(如drawable,style等)命名必须以全部单词小写,单词间以下划线分割,并且尽可能的使用名词或名词组,即使用[模块名_用途] 来命名。如果为公共资源,如分割线等,则直接用用途来命名.
只能使用a-z,0-9,和“_”组成,并且不能单独使用数字作为资源名称。
2.8 图片命名
应用于res/drawable目录下的文件。该目录下可能存在静态图片文件,动态图片文件和选择器(selector),静态图片是指只有一种状态的图片,动态图片是指由多种状态的图片,例如按钮按下和放开时的不同状态图片,选择器是指包含动态图片组合的xml文件。
2.8.1 静态图片
- 范围:
res/drawable目录下的静态图片,静态图片是指只有一种状态的图片,如背景图片、图标。
- 命名规范:
[前缀模块]、[前缀模块_描述]、[描述]
前缀:类别的缩写(参照表 1 - 前缀)
模块:使用该文件的模块
描述:描述该文件的功能
Ø 例如:
bg\_main.png
ic\_feedback\_send.png
menuitem\_save.png
2.8.2 动态图片
- 范围:
res/drawable目录下的动态图片,静态图片是指只有多种状态的图片,如按钮(button)、状态图片、选择按钮(radio button)状态图片。
- 命名规范:
[前缀_描述状态]、[前缀模块_描述_状态]
前缀:文件类别的缩写(参照表 1 - 前缀)
模块:使用该文件的模块
描述:描述该文件的功能
状态:该图片的所表示的状态(参照表 2 –后缀)
Ø 例如:
btn\_film\_buy\_nor.png
btn\_film\_buy\_press.png
btn\_back\_nor.png
btn\_back\_press.png
2.8.3 选择器(selector)
- 范围:
res/drawable目录下的选择器,选择器是指包含动态图片组合的xml文件。
- 命名规范:
[前缀描述]、[前缀模块_描述]
前缀:类别的缩写(参照表 1 - 前缀)
模块:使用该文件的模块
描述:描述该文件的功能
Ø 例如:
btn\_film\_buy.xml
btn\_back.xml
rbtn\_film.xml
2.8.9 动画文件命名
- 范围:
res/anim文件夹下面,为一些动态效果文件
- 命名规范:
[前缀描述]、[前缀模块_描述]
全部小写,采用下划线命名法,加前缀区分。(参照表4–动画)
前缀: 动画的类型
模块:使用该文件的模块
描述:动画的方向
Ø 例如:
fade\_in.xml
push\_down\_out.xml
- 表1 - 前缀
ic – icon:主要用于布局和子布局的图标
bg – background:主要用于布局和子布局的背景
div – divider:主要用于分隔线,不仅包括Listview中的还包括普通布局中的线
btn – button:主要用于按钮的表示
- 表2 - 后缀
unit:在使用xml的tilemode来配图片时,element图片使用此后缀
nor:图片的状态,代表普通状态
hl:图片的状态,代表高亮状态
press:图片的状态,代表按下状态
select:图片的状态,代表其所占的view被选中
unselect:图片的状态,代表其所占的view没有被选中
- 表3 - 组件缩写
Button:Btn(btn)
RadioButton:Rbtn(rbtn)
ImageButton:Ibtn(ibtn)
TextView:Tv(tv)
ImageView:Iv (iv)
ListView:Lv(lv)
ProgressBar:Pbar(pbar)
EditText:Edtv(et)
ScrollView:Sclv(scly)
CheckBox:Chk(chk)
RelativeLayout:Rlyt(rlyt)
LinearLayout:Llyt(llyt)
TableLayout:Tlyt(tlyt)
AbsoluteLayout:ALyt(alyt)
FrameLayout:Flyt(flyt)
DigtalClock:DgtClk(dgtclk)
analogClock:AnaClk(anaclk)
DatePicker:DtPk(dtpk)
TimePicker:TmPk(tmpk)
ToggleButton:TgBtn(tgbtn)
SeekBar:SkBar(skbar)
AutoCompleteTextView:AutoTv(autotv)
ZoomControls:ZmCtl(zmctl)
VideoView:Vidv(vidv)
WebView:Wv(wv)
RantingBar:RtBr(rtbr)
MapView:Mapv(mapv)
Spinner:Spn(spn)
Chronometer:Cmt(cmt)
TextSwitch:TeSw(tesw)
ImageSwitch:ImgSw(imgsw)
ExpandableList:EpdLt(epdlt)
- 表4–常见动画文件命名
fade_in:淡入
slide_in_from_top:从头部滑动进入
fade_out:淡出
zoom_enter:变形进入
push_down_in:从下方推入
slide_in:滑动进入
push_down_out:从下方推出
shrink_to_middle:中间缩小
push_left:推向左方
2.9 Value命名
2.9.1 color命名
如果是android系统有原生的,就用原生的颜色,譬如白色,黑色,透明,深灰,浅灰等
一般控件和背景色中都会用到的颜色,命名规则:颜色。例如 blue,dark_blue,sky_blue, sapphire_blue
多个界面某种控件会用到的颜色,命名规则:控件缩写_颜色。例如btn_blue
某个界面中专有控件会用到的颜色,命名规则:[控件缩写_模块_颜色]。例如txt_menu_light_blue, btn_title_blue
2.9.2 dimens命名
一些常量的常规定义,例如:
<dimen name="default\_padding\_0.5x">5dp</dimen>
<dimen name="default\_padding\_0.2x">2dp</dimen>
<dimen name="default\_padding\_1x">10dp</dimen>
<dimen name="default\_text\_size\_big">18sp</dimen>
<dimen name="default\_text\_size\_normal">16sp</dimen>
2.9.3 Strings命名
在多个界面中需要用到的字符串可放在各分类的normal下,例如normal分类可包括:
<!-- normal text -->
<stringname="text\_null">null</string>
<stringname="text\_login">登录</string>
<!--nornal dialog -->
<stringname="dialog\_loading">数据加载中…</string>
<stringname="dialog\_tips">提示</string>
<!--nornmal toast -->
<stringname="toast\_error\_404">找不到服务器</string>
<stringname="toast\_server\_error">系统繁忙,请稍后再试</string>
若只在一个界面中用到,可放在各自activity或者fragment注释下,命名规则仍旧遵循normal的格式,该显示在dialog中,name就以dialog开头,是显示hint的,用hint开头,后面加上模块描述:例如:
<!-- title -->
<stringname="hint\_title\_search\_key">搜索关键字</string>
<stringname="text\_title\_notification">通知</string>
<!-- login activity -->
<stringname="hint\_login\_email">邮箱地址</string>
<!-- change pwd activity -->
<stringname="text\_change\_pwd\_old\_pwd">旧密码</string>
3.代码规范
3.1 通用规范
3.1.1 变量赋值
避免在一个语句中给多个变量赋相同的值。它很难读懂。如下面例子。
不推荐:
fooBar.fChar = barFoo.lchar = 'c'
推荐:
fooBar.fChar = 'c'
barFoo.lchar = 'c'
不要将赋值运算符用在容易与相等关系运算符混淆的地方。
不推荐:
if (c++ = d++) { // (Java disallows)
...
}
推荐:
if ((c++ = d++) != 0) {
...
}
不要使用内嵌(embedded)赋值运算符试图提高运行时的效率,这是编译器的工作。
不推荐:
d = (a = b + c) + r;
推荐:
a = b + c;
d = a + r;
3.1.2 圆括号
一般而言,在含有多种运算符的表达式中使用圆括号来避免运算符优先级问题。
不推荐:
if (a == b && c == d)
x >= 0 ?x : -x
推荐:
if ((a == b) && (c == d))
(x >= 0) ?x : -x
3.1.3 返回值
设法让你的程序结构符合目的。
不推荐:
if (booleanExpression) {
return true;
} else {
return false;
}
if (condition) {
return x;
}
return y;
推荐:
returnbooleanExpression;
return (condition ? x : y);
3.2 注释
Java 程序有两类注释:实现注释(implementation comments)和文档注释(document,comments)。实现注释是使用/…/和//界定的注释。文档注释(被称为”doc comments”),由/*…/界定。
3.2.1 文件注释
所有的源文件都应该在开头有一个注释,其中列出类名、版本信息、日期和版权声明。如下:
/*
* 文件名
* 包含类名列表
* 版本信息,版本号
* 创建日期
* 版权声明
/
3.2.2 类注释
每一个类都要包含如下格式的注释,以说明当前类的功能等。
/*
* 类名
* @author 作者
* 实现的主要功能。
* 创建日期
* 修改者,修改日期,修改内容。
*/
3.2.3 方法注释
每一个方法都要包含如下格式的注释包括当前方法的用途,当前方法参数的含义,当前方法返回值的内容和抛出异常的列表。
/*
* 方法的一句话概述
* 方法详述(简单方法可不必详述)
* @params说明参数含义
* @return 说明返回值含义
* @throws IOException说明发生此异常的条件
* @throws NullPointerException说明发生此异常的条件
/
3.2.4 类成员变量和常量注释
成员变量和常量需要使用java doc形式的注释,以说明当前变量或常量的含义。
/*
* XXXX含义
/
3.2.5 其他注释
方法内部的注释如果为多行,使用/„„ /形式,如果为单行,使用//„„形式的注释。不要再方法内部使用 java doc 形式的注释“/*„„**/”。
3.3 Log规范
Log所打印出来的信息应具有可读性,不要打印只有自己能看懂的log,例如“1”、“Finish”等。
不推荐:
Log.d("MainActivity", "success");
Log.d(TAG, "1");
推荐:
Log.d("MainActivity", "Get user info successfully");
Log.d(TAG, "Search finished. Get user id: 1");
使用规范的log分类,例如调试的信息使用DEBUG,错误的信息使用ERROR。
注意发布版本的log中不能打印敏感信息,防止隐私泄漏。
临时的用来调试的log应尽量使用DEBUG 和VERBOSE。
4.代码格式化
4.1在Eclipse中导入Formatter和Importor
4.1.1 注释模板
preferences 中,选择 java → code style → formatter 中选择 Import,选择formatter.xml。
4.1.2 添加文件创建日志模板
preferences 中,选择 java → code style → code Template 中选择 >Import,选择codetemplates.xml。但是注意修改类注释和文件注释的作者名称为自己的。
4.1.3 XML格式化:
preferences中,选择xml → xml files→ xml editor中做如下设置。
4.2 在Android studio中导入Formatter和Importor
4.2.1 注释模板:
在Android studio的File中,选择Settings,点击Editor → File and Code Templates → Includes→ File Header。
4.2.2 Android Studio设置代码风格
在Android studio的File中,选择Settings,然后搜索CodeStyle选择Java进入如下界面搜索java,进入Code Style 中的java设置如下编码风格。
5.推荐规范
5.1 一个方法尽量不要超过15行。
如果方法太长,说明当前方法业务逻辑已经非常复杂,那么就需要进行方法拆分,保证每个方法只作一件事。
5.2 代码中不允许出现单独的数字,字符!
如果需要使用数字或字符,则将它们按照含义封装为静态常量!(for语句中除外)
5.3 所有if 语句最好用{}包括起来,即便是只有一句:
推荐:
if (true){
//do something......
}
不推荐:
if (true)
i = 0;
5.4 对于循环
推荐:
//将操作结构保存在临时变量里,减少方法调用次数
final int count = products.getCount();
while(index < count){
}
不推荐:
while(index <products.getCount()){
//每此都会执行一次getCount()方法,
//若此方法耗时则会影响执行效率
//而且可能带来同步问题,若有同步需求,请使用同步块或同步方法
}
5.5 控制访问
若没有足够理由,不要把实例或类变量声明为公有。通常,实例变量无需显式的设置(set)和获取(gotten),通常这作为方法调用的边缘效应 (side effect)而产生。
一个具有公有实例变量的恰当例子,是类仅作为数据结构,没有行为。亦即,若你要使用一个结构(struct)而非一个类(如果java 支持结构的话),那么把类的实例变量声明为公有是合适的。