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的命名规则:
<resource>
<color name="white_FFFFFF">#FFFFFF</color>
</resource>
值得一提的是,这样规范的颜色很容易修改或重构,App所使用的颜色数量和种类也会变得非常清晰,特别是UI校对时。
相反地,不使用以下对色值的命名规则:
<resource>
<color name="button_background">#FFFFFF</color>
<resource>
使用这种定义方式,我们需要非常的谨慎,一不小心就会重复定义ARGB,而且当改变基本色时,会造成毫无意义的重复操作。
Dimen相关
我们应该像对待colors.xml一样对待dimens.xml文件,与定义“调色板”无异,同样应该为字体定义一块“字号版”,字体都用dp。
要使用以dimen_作为前缀的命名规范:
<resource>
<dimen name="dimen_640dp">640dp</dimen>
</resource>
这样写的好处是,使组织结构和修改布局风格变得非常容易,同时也避免了对重复数值的定义。
String相关
对string的声明必须添加业务区分标识,前缀应该能清楚地表达功能职责,如,registration_email_hint,registration_name_hint。如果一个Sting不属于任何模块,就意味着它是通用的,遵循以下规范:
另外,需要注意的是,所有用作UI展示的字符串都必须定义在string.xml文件中,不准出现在java或者layout布局中
Style与Theme相关
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所修饰,并且命名应该符合以下规范:
Activity和Fragment打开方式
当通过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等
网友评论