美文网首页UIT
Android编码规范

Android编码规范

作者: Chris锅 | 来源:发表于2017-11-23 17:22 被阅读15次

    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布局中

    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_widthandroid:layout_height属性放到一个style.xml中作为一个通用的风格更有意义,但是默认情况下把这些属性放到Layout文件中比放到style.xml文件中更加直观。

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

    避免层级冗余的嵌套

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

        本文链接:https://www.haomeiwen.com/subject/ypazvxtx.html