Android Code Standard

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),接口一般要使用ableibleer等后缀。

Ø 例如:

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">数据加载中&#8230;</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)和文档注释(documentcomments)。实现注释是使用//和//界定的注释。文档注释(被称为”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 中,选择 javacode styleformatter 中选择 Import,选择formatter.xml

4.1.2 添加文件创建日志模板

preferences 中,选择 java → code stylecode Template 中选择 >Import,选择codetemplates.xml。但是注意修改类注释和文件注释的作者名称为自己的。

4.1.3 XML格式化:

preferences中,选择xmlxml filesxml editor中做如下设置。

4.2 在Android studio中导入Formatter和Importor

4.2.1 注释模板:

Android studioFile中,选择Settings,点击EditorFile and Code TemplatesIncludesFile Header

4.2.2 Android Studio设置代码风格

Android studioFile中,选择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 支持结构的话),那么把类的实例变量声明为公有是合适的。

I Don't Want Your Money, I Want Aragaki Yui.