Android编码规范

androidstudio集成checkstyle提交前校验方法,将pre-commit文件copy到工程目录.git/hooks下并且在该目录执行chmod a+x pre-commit赋予权限

Android 编码规范

1.1 代码需要规范

代码之于程序员,就像零件之于机械工,庄稼之于农民,它是软 件的基石,一行行代码都是程序员的心血经过日日夜夜凝结成的。做 为一个程序员,应该像母亲呵护孩子一样呵护自己的代码,它不仅仅 是一行一行的文字,它是一个程序员的尊严和价值所在;它是活的, 你甚至能感受到它的心跳。编码规范只是大家达成一致的约定,这样 大家的代码就可以互相看懂,维护起来更加容易,思想更畅快的交流, 经验更快的得到传播。代码规范不是束缚程序员的桎梏,应该知道, 不遵守规范的个性的代码并不代表程序员的性格,并不能张扬个性。 个性应该体现在用更简单、更优雅、更易读、更易理解以及算法实现 效率更高等方面。

可读性,可理解性是代码的重要方面,本规范主要围绕如何去产 生规范 易读的代码。另外,它也保证了大家有共同的先验知识。

第二章 重要规范

2.1 操作规范

1.模板及格式化 开发人员必须保证代码格式化的一致性,否则可能会导致代码冲

突,轻微的耗费人力合并代码;严重时可能导致代码丢失,引起 bug 或者故障。

2. 代码提交

为防止冲突,代码(及配置文件)提交前,先从 git 中更新代码 和配置文件,尽早发现不兼容的代码和冲突。 提交代码(及配置文 件)时,如果发生冲突时,先看历史说明,再找相关人员确认,

坚 决 不允许强制覆盖。每次提交代码之前,必须检查是否有 warning,并 FIX 所有的 warning。

1.禁止采用删除主干文件添加新文件的方式来更新代码,将 导致版本树丢失,无法查看历史版本

2.禁止提交带有警告的代码

3.禁止提交开发用脏代码

4.禁止提交线下(local)配置相关代码

5.禁止提交无法编译的代码

6.禁止通过覆盖的方式合并代码

7.提交代码务必保证他人能顺利编译工程,不要忘记提交新文件、不要提交绝对路径相关的配置

8.提交代码务必保证模拟器和手机都能正常运行

9.提交通过自动化测试的代码

3.垃圾清理对于完全没有用到的,或者被注释掉的类、方法、配置文件、资源文件等要坚决从工程中清理,避免造成过多垃圾。 特别是在删除、更新模块时,res、assets 目录下的相关资源文件也要一并清除。

4.提交备注

如果使用类似$ git commit等语句,建议采用以下规范添加完整的提交备注

标题与内容之间保持一个空行,示例如下:

Fixed #<此bug在bug管理工具上的索引、路径或其他标识>内容部分添加简短描述,如改动原因,主要变动或者一些重要的建议事项。最后如果有需要可以添加对应的网址,如bug地址等。

如果使用$ git commit -m""等语句,建议采用以下规范添加简短的提交备注

如果真的没有什么详细内容可以描述,使用简短的提交备注形式,是一种不错的选择,示例如下:

git commit -m 'Fixed #[issue number]: [Short summary of the change].'

下面是几个常用提交动词,以供参考:https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit

feat: A new feature

fix: A bug fix

docs: Documentation only changes

style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)

refactor: A code change that neither fixes a bug nor adds a feature

perf: A code change that improves performance

test: Adding missing or correcting existing tests

2.2 日志规范

1. 日志输出

代码禁止以系统的方法输出日志信息,必须用

LogUtil替代。

2 异常处理

捕捉到的异常,不允许不做任何处理就截断,至少要记入日志, 或重新抛出。最外层的业务使用者,必须处理异常,将其转化为用户 可以理解的内容。

代码中所有的 try-catch,必须在 catch 到异常时加入LogUtil.e 日 志,打印错误信息。

2.5 参数校验

对参数合法性的判断必须收敛到方法级别,对使用到的对象进 行判空等校验,防止出现空指针和数组越界等低级错误。对于在多个 方法内被调用的全局变量,也必须执行校验,总之你不确定或者外部可以改变的对象,都要进行判空操作。

2.6 安全规范

1. 系统安全 页面创建的多线程的情况(例如网络连接),必须加上防重复创建策略,如果页面退出,此页面相关的线程必须明确的退出,不允许后 台继续运行,并及时释放所占用内存。

2. 保护敏感信息

用户的敏感信息包括密码、短信验证码、手机号等信息严禁 泄 露,否则可能会带来不安全因素。可能会导致敏感信息泄露的方 式有:Log、URL 的 get 参数(因为 URL 的 get 参数会在 apache 日 志中被输出)、没有加密直接存在本地数据库等。

2.7 通用规范

1.方法作用需要单一,只做一件事情。阅读上千行的代码是一个巨大的挑战。

方法的参数应该尽量避免三个以上,对于太多的参数可以采用参 数对象。

2. 代码复用

1.禁止在已有工具类、接口的情况下重复实现

2.在 gson format 自动生成的数据类满足条件时,禁止进行二次封装

3.超过三处使用同一代码块,必须提出为公共方法

4.禁止无脑 Copy 代码,多个模块代码接口类似、功能接近时,考虑使用模板实现

5.配置信息的使用避免将系统参数、URL、文件名、系统开关、业务规则等参数硬编码,需要写入配置文件,方便修改。

6. 禁止硬编码 ,使用到的常量,必须定义在 Constant 类中。

第三章 命名规范

3.1 一般命名规范 (命名不要使用拼音)

1. 变量名与模块、接口名称应统一 例如帐号模块,工程名为“Account”,相关类、方法、资源中就应 以 account 命名,禁止使用其他例如“charge”、“identify”、“zhangsan” 等命名。

2.包名应用小写字母,禁止出现下划线等符号,名词用有意义的缩 写或者英文单词。例如:com.tencent.account ,避免: com.tencent_account.android。

3.类命名--所有单词第一个字母大写,其它字母小写,使用名词组合, 例如:UserManager, ClassLoader, HttpHeaderResult。

4.Data层面,接口命名使用字母“I”开头,所有单词第一个字母大写,其它字母 小写,如:IQuery,IDataAccess,IReportBuilder。

5.View层面,使用名词组合或形容词去命名一个接口,接口声明了一个对象能 提供的 服务,也描述了一个对象的能力。一般以“able”和“listener”作为 后缀, 代表了一种能力,例如:public interface Clickable{}、public interface OnItemClickListener等。

6.变量命名--除了第一个单词,所有单词第一个字母大写,例如: userName, objectFactory, list,成员变量以m开头。

7. 对于常量名,使用大写字母,并使用下划线做间隔,例如: MAX_TIMES, DEFAULT_NAME。

8. 方法名应该使用动词开头,除了第一个单词,所有单词第一个字 母大写,一般由动词+名词组成,例如:getName, addParameter。

9.缩写字母也应该保持首字母大写,例如:exportHtmlSource(),避 免: exportHTMLSource()。

10.变量的名字应该和类型名称一致,例如:void setTopic(Topic topic) ,避免: void setTopic(Topic value)。

当同时定义多个属于同一个类的变量时,把类型作为实例的后缀, 例如: Point startPoint,Point endPoint这样是为了从实例名就可以推断它的类型 名称。

11. 根据变量的作用范围,作用范围大的应该使用长名称,作用范围大,表明变量的生命周期比较长,为了有助于理解,应尽量用长名称 以表达变量的真实意图。反之,对于作用范围小,可以使用一些简化 的名称,比如 i、j、k 等,提高编程效率。

3.2 特殊命名规范

2.使用 is 前缀表示一个布尔变量和方法,例如:isUsed, isEmpty,isVisible,isFinished。有时也可以使用 has,can,should: boolean hasLicense();boolean canEvaluate();boolean shouldAbort();

3.在查询方法中应使用 find 作为前缀,例如: searchPostDb.findLastSearchKey。

4.使用 initialize 做为对象初始化的方法前缀,也可以简写为 init, 例如:initializeFiles(),init(),initFontSet()。

5.对于对象集合,变量名称应使用复数,例如:Collection points。

6. 对于抽象类,应该使用 Abstract 前缀,例如: AbstractReportBuilder,AbstractBeanFactory。

7. 常在一起使用的对称词汇,这些词汇一起使用,方法的表达意图 自然可以互相推测和演绎,例如: get/set, add/remove, create/destroy,start/stop, begin/end, first/last, up/down, min/max, next/previous, open/close, show/hide。

8.禁止使用否定布尔变量,例如:bool isError,避免: isNoError。

9.异常类应该使用 Exception 做为后缀,例如:AccessException。

10. 缺省接口实现应该使用 Default 前缀,例如:Class DefaultTableCellRenderer implements TableCellRenderer {}。

11.对于单例类(Singleton),应该使用 getInstance 方法得到单例。

12. 对于工厂类,进行创建对象的方法,应该使用 new 前缀,例如: class PointFactory {

public Point newPoint(...) {} }。

写在开头:强制遵循的规范使用绿色标注,必须不允许的规范使用红色标注,建议遵循的使用紫色标注

3.3 资源命名规范

XML文件

资源等.xml文件要采用小写字母_下划线的组合形式。

Drawable相关

Drawable文件建议命名方式:

icon文件建议命名方式:

selector states文件建议命名方式:

Layout相关

Layout文件建议命名方式:

布局文件应该与Android组件的命名相匹配,以组件类型作为前缀,并且能够清晰的表达意图。例如:如果为SignInActivity创建一个布局文件,那么应该命名为activity_sign_in.xml。建议采用以下基本命名规则:

值得一提的是,一些布局文件需要通过Adapter填充,如ListView,Recyclerview等列表视图,这种场景下,布局的命名应该以item_作为前缀。另外还有一种比较常见的情况,一个布局文件作为另一个布局文件的一部分而存在,或者使用了include,merge等标签的布局,建议使用partial_、include_或者merge_作为前缀,这一类布局的命名同样应该清晰的表达其意图。

Id命名方式:

控件Id的命名应该以该控件类型的缩写作为前缀,同样要使用小写字母_下划线的组合形式,能够清晰表达意图是命名的前提:

示例如下:

```

android:id="@+id/iv_profile"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

android:id="@+id/menu_done"

android:title="Done"/>

```

Color相关

colors.xml可以比喻成“调色板”,只映射ARGB值,不应该存在其他类型的数值,更不要使用它为不同的按钮来定义ARGB。

应该根据颜色或者风格对ARGB赋值,要使用基色_ARGB的命名规则:

#FFFFFF

值得一提的是,这样规范的颜色很容易修改或重构,App所使用的颜色数量和种类也会变得非常清晰,特别是UI校对时。

相反地,不使用以下对色值的命名规则:

#FFFFFF

使用这种定义方式,我们需要非常的谨慎,一不小心就会重复定义ARGB,而且当改变基本色时,会造成毫无意义的重复操作。

Dimen相关

我们应该像对待colors.xml一样对待dimens.xml文件,与定义“调色板”无异,同样应该为字体定义一块“字号版”,字体都用dp。

要使用以dimen_作为前缀的命名规范:

640dp

这样写的好处是,使组织结构和修改布局风格变得非常容易,同时也避免了对重复数值的定义。

String相关

对string的声明必须添加业务区分标识,前缀应该能清楚地表达功能职责,如,registration_email_hint,registration_name_hint。如果一个Sting不属于任何模块,就意味着它是通用的,遵循以下规范:

另外,需要注意的是,所有用作UI展示的字符串都必须定义在string.xml文件中,不准出现在java或者layout布局中

StyleTheme相关

Style与Theme的命名统一使用驼峰命名法。请谨慎使用style与theme,避免重复冗余的文件出现。可以出现多个styles.xml文件,如:styles.xml,style_home.xml,style_item_details.xml,styles_forms.xml等。

另外值得一提的是:res/values目录下的文件可以任意命名,但前提是该文件能够明确表达职责所属,因为起作用的并不是文件本身,而是内部的标签属性。

编码规范与指导方针

XML文件规范

使用tools标签预览视图

布局预览建议使用tools:****相关属性,避免android:text="Hardcode"等硬编码的出现,具体可参考Designtime attributes。

要使用如下示例方式设置属性:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

tools:text="Tencent"/>

不要使用以下硬编码方式:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Tencent"/>

通用style

值得一提的是,android:layout_****属性应该在XML中定义,同时其它属性android:****应放在style中。核心准则是保证Layout属性(position, margin, size等)和content属性在布局文件中,同时将所有的外观细节属性(color, padding, font)放在style文件中。

另外,在上面提到的准则中,有以下几点需要注意:

android:id明显应该在layout文件中

Layout文件中的android:orientation属性对于一个LinearLayout布局来说,更具有意义

由于使用android:text定义内容,所以这个属性应该放在Layout文件中

有时候将android:layout_width和android:layout_height属性放到一个style.xml中作为一个通用的风格更有意义,但是默认情况下把这些属性放到Layout文件中比放到style.xml文件中更加直观。

只有通用组件使用style,其他组件不必使用。

避免层级冗余的嵌套

Layout结构优化方面,应尽量避免深层次的布局嵌套,这不仅会引发性能瓶颈,还会带来项目维护上的麻烦。在书写布局之前应该对ViewTree充分的分析,善用标签减少层级嵌套,或者使用Hierarchy Viewer等UI优化工具对Layout进行分析与优化。可参考Optimizing Your UI与Optimizing Layout Hierarchies。

注解使用规范

@Override:子类实现或者重写父类方法时,必须使用@Override对函数进行标注。

@SuppressWarnings:注解@SuppressWarnings应该用在消除那些明确不可能发生的警告上,示例如下:

//明确的类型安全(type-safe)转换

@SuppressWarnings("unchecked")

public static FeedbackUseCase createdUseCase(){

return (FeedbackUseCase) new FeedbackUseCase();

}

//请先确保能够非常正确地使用Handler

@SuppressWarnings("handlerLeak")

private Handler mHandler=new Handler(){

@Override

public void handleMessage(Messagemsg){

super.handleMessage(msg);

}

};

更多关于注解的使用技巧与规范请参考这里,或者使用android.support.annotation依赖包中的注解优化程序。

如果继承了Android组件,比如Activity或者Fragment,重写生命周期函数时,建议按照组件的生命周期进行排序,如:

public class MainActivity extends Activity{

@Override

public void onCreate(){}

@Override

public void onResume(){}

@Override

public void onPause(){}

@Override

public void onDestroy(){}

}

方法函数中的参数排序规范

在Android日常开发中,很多情况下都需要使用Context,所以经常被作为参数传入方法中,这里给出的建议是,如果函数签名中存在Context,则作为第一个参数,如果存在Callback则作为最后一个参数,示例如下:

public void loadUserAsync(Context context,int userId,UserCallback callback);

字符串常量的命名与赋值规范

Android SDK中诸如SharedPreferences,Bundle和Intent等,都采用key-value的方式进行赋值,当使用这些组件时,key必须被static final所修饰,并且命名应该符合以下规范:

ActivityFragment打开方式

当通过Intent或者Bundle向Activity与Fragment传值时,应该遵循上面提到的key-value规范,公开一个被public static修饰的方法,方法的参数应该包含所有打开这个Activity或者Fragment的信息,示例如下:

通过.startIntent()函数,开启指定Activity。

public static void startActivity(AppCompatActivity startingActivity,User user){

Intent intent=new Intent(startingActivity,ThisActivity.class);

intent.putParcelableExtra(EXTRA_USER,user);

startingActivity.startActivity(intent);

}

通过.newInstance()函数,加载指定Fragment。

public static UserFragment newInstance(User user){

UserFragment fragment=new UserFragment();

Bundle args=newBundle();

args.putParcelable(ARGUMENT_USER,user);

fragment.setArguments(args)

return fragment;

}

需要注意一下两点:

以上这些方法应该放在类的开头,至少应该放在.onCreate()之前。

Intent中所涉及的key,如EXTRA_USER,ARGUMENT_USER等,如果与其他业务无关,应该放在本类中被private所修饰,不暴露给其它外部类。如果是通用key,则应该声明在公共Common文件中。

第四章 格式规范1. 类和接口中元素的布局顺序

类和接口的文档描述

类和接口的声明

类的静态变量,按照 public,protected,package,private 的顺序

实例变量,按照 public,protected,package,private 的顺序 类的方法,无固定顺序

2. 方法修饰关键字定义顺序

static abstract synchronized

unuaual final native methodName,访问标示符一定要在最前面。

3. 变量声明,不要在一行声明多个变量,避免:int level, size;

4. 保证明确的类型转换,不要默认进行隐式类型转换,例如: intValue = (int) floadValue,避免:intValue = floatValue。

5. 数组指示符紧跟类型变量,例如:int[]a = new int[20],避免: int a[] = new int[20]。

7. 仅仅循环控制变量才能出现在 for()循环中,例如: sum = 0;

for (i = 0; i < 100; i++) {

sum += value[i]; 

}

避免:

for (i = 0, sum = 0; i < 100; i++){

sum += value[i]; 

}

8. 循环变量应靠近循环体初始化,例如: isDone = false while(!isDone){}

避免:

isDone = false;

...

... while(!isDone){}

9.避免长的布尔表达式,应换成多个更容易理解的表达式,例如: bool isFinished = (elementNo < 0) || (elementNo > maxElement); bool isRepeatedEntry = elementNo == lastElement;

if (isFinished || isRepeatedEntry) {...}

避免:

if ((elementNo < 0) || (elementNo > maxElement)|| elementNo == lastElement) {...}

10.不要在条件语句中执行方法,以提高可读性,例如: InputStream stream = File.open(fileName, "w");

if (stream != null) {...}

避免:

11. 条件语句的主要形式,即使单条语句,也要使用括号括起来。

12. 空循环体也要使用完整的{}块

for (initialization; condition; update) {

... }

13. switch 语句的使用格式 switch (condition) {

case ABC :

statements;

//穿透,一定要做出注释

case DEF : statements;

break; default :

statements;

break; }

14. try-catch 使用格式 try {

statements;

} catch (Exception exception) {

statements; } finally {

statements; }

第五章 注释规范

5.3 注释内容

代码注释内容与顺序:

2. 简介

3. 严格注意事项

4. 详细说明/备注/场景 5. 参数

6. Return

7. exception

8. See

9. deprecated 说明

文件头注释

关于文件头注释这里给出统一的模板和编写规则,务必声明创建该类的时间,作者以及对该类的功能描述

1.对于新创建的类,可以使用静态模板的方式,自动生成文件头,然后对其进行编写:

该模板如下:

/**

*

创建时间: ${YEAR}/${MONTH}/${DAY} ${HOUR}:${MINUTE}

*

描述:

*/

2.使用动态模板,重构已经存在的文件头:

该模板格式如下:

/**

*

创建时间: $date$ $time$

*

描述:

*/

关于第二种方式,如在"abbreviation"一栏中填写的是“cc”,只需将光标移至文件头,输入“cc”后便会出现代码提示,点击回车或者Tab键,然后编写生成的文件头即可。

Field定义与命名规范

对Field的定义应该放在文件的首位,并且遵守以下规范:

非静态变量,以m作为前缀

静态变量,以s作为前缀

静态常量命名字母全部大写,单词之间用下划线分隔

示例:

public class MyClass{

public static final int SOME_CONSTANT=42;

public int public Field;

private static MyClasss Singleton;

int mPackagePrivate;

private int mPrivate;

protected int mProtected;

extra:

不要仅仅依赖@NonNull 而忘记安全判断

建议 bug修复的代码提交备注bug编号例如:update bug fix #1605

model里如无特殊情况,用int代替Integer,用float代替Float等

你可能感兴趣的:(Android编码规范)