Android编程规范

前言

  • 好的命名规则能够提高代码质量,使得新人加入项目的时候降低理解代码的难度;
  • 规矩终究是死的,适合团队的才是最好的;
  • 命名规范需要团队一起齐心协力来维护执行,在团队生活里,谁都不可能独善其身;
  • 一开始可能会有些不习惯,持之以恒,总会成功的。

制定好了规范,就要遵守,有了统一的规范,项目才好维护,相互之间才好review代码,便于开发与维护。

 

一、编程规范

(一)命名风格

1、类命名: 命名用大驼峰命名法,每一个单词的首字母都大写

 

描述

例如

Activity 类Activity 为后缀标识登录类 LoginActivity
Adapter 类Adapter 为后缀标识聊天适配器 ChatAdapter
解析类Parser 为后缀标识首页解析类 HomePosterParser
工具方法类Utils 或 Manager 为后缀标识线程池管理类:ThreadPoolManager
日志工具类:LogUtils
打印工具类:PrinterUtils
数据库类以 DBHelper 后缀标识信息流数据库:MomentsDBHelper
Service 类以 Service 为后缀标识时间服务 TimeService
BroadcastReceiver 类以 Receiver 为后缀标识推送接收 JPushReceiver
ContentProvider 类以 Provider 为后缀标识ShareProvider
自定义的共享基础类以 Base 开头BaseActivityBaseFragment
测试类以Test 为后缀标识MomentsTest

 

 

2、常量命名:全部字母大写,用下划线分隔单词

如:HT_DB_VERSION

Android SDK 中的很多类都用到了键值对函数,比如 SharedPreferencesBundleIntent,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。

当时用到这些类的时候,我们 必须 将它们的键定义为 static final 字段,并遵循以下指示作为前缀。

字段名前缀

SharedPreferencesPREF_
BundleBUNDLE_
Fragment ArgumentsARGUMENT_
Intent ExtraEXTRA_
Intent ActionACTION_

 

说明:虽然 Fragment.getArguments() 得到的也是 Bundle ,但因为这是 Bundle 的常用用法,所以特意为此定义一个不同的前缀。

例如:

// 注意:字段的值与名称相同以避免重复问题
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";

// 与意图相关的项使用完整的包名作为值的前缀
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";

 

 

3、非常量字段名:命名用小驼峰命名法,第一个单词的首字母小写,后面的单词的首字母全部大写

 

分类

描述

例如

成员变量

非公有,非静态字段命名以 m 开头。

静态字段命名以 s 开头。

公有字段命名以public开头。

其他字段以小写字母开头。

boolean命名以**开头。(待讨论)

public class MyClass {

    public int publicField;

    private static MyClass sSingleton;

    int mPackagePrivate;

    private int mPrivate;

    protected int mProtected;

}

局部变量

用小驼峰命名法以小写字母开头即可,但尽量避免用单个字符命名mainTitle
临时变量

临时变量通常被取名为 ijkm 和 n,它们一般用于整型;

for (int i = 0; i < len; i++)

控件类型

Android 众多的 UI 控件,为避免控件和普通成员变量混淆以及更好地表达意思,所有用来表示控件的成员变量统一加上控件缩写作为前缀。详见UI 控件缩写表

mIvAvatar、rvBooks、flContainer

 

数据类型

对于表示集合或者数组的非常量字段名,我们可以添加后缀来增强字段的可读性,比如:

集合添加如下后缀:List、Map、Set。

数组添加如下后缀:Arr。

mIvAvatarListuserArrfirstNameSet
量词

变量名中可能会出现量词,我们需要创建统一的量词,它们更容易理解,也更容易搜索,比如:

First: 一组变量中的第一个
Last: 一组变量中的最后一个
Next: 一组变量中的下一个
Pre: 一组变量中的上一个
Cur: 一组变量中的当前变量

mFirstBookmPreBookcurBook

 

 

 

UI 控件缩写表

 

名称

缩写

Buttonbtn
CheckBoxcb
EditTextet
FrameLayoutfl
GridViewgv
ImageButtonib
ImageViewiv
LinearLayoutll
ListViewlv
ProgressBarpb
RadioButtionrb
RecyclerViewrv
RelativeLayoutrl
ScrollViewsv
SeekBarsb
Spinnerspn
TextViewtv
ToggleButtontb
VideoViewvv
WebViewwv

 

 

3、方法命名:命名用小驼峰命名法

方法名通常是动词或动词短语。

 

 

方法

说明

initXX()初始化相关方法,使用 init 为前缀标识,如初始化布局 initView()
isXX()checkXX()方法返回值为 boolean 型的请使用 is/check 为前缀标识
getXX()返回某个值的方法,使用 get 为前缀标识
setXX()设置某个属性值
handleXX()processXX()对数据进行处理的方法
displayXX()showXX()弹出提示框和提示信息,使用 display/show 为前缀标识
updateXX()更新数据
saveXX()insertXX()保存或插入数据
resetXX()重置数据
clearXX()清除数据
removeXX()deleteXX()移除数据或者视图等,如 removeView()
drawXX()绘制数据或效果相关的,使用 draw 前缀标识

 

4、自定义View命名:命名用大驼峰命名法

如:xxxView,xxxLayout

 

 

5、布局文件命名(layout/)

 

布局文件分别要以activity_,fragment_,layout_ ,item_ 等开头。

命名规则:类型_模块名类型{_模块名}_逻辑名称

说明:{} 中的内容为可选。

例如:

名称

说明

activity_main.xml主窗体 类型_模块名
activity_main_head.xml主窗体头部 类型_模块名_逻辑名称
fragment_music.xml音乐片段 类型_模块名
fragment_music_player.xml音乐片段的播放器 类型_模块名_逻辑名称
dialog_loading.xml加载对话框 类型_逻辑名称
ppw_info.xml信息弹窗(PopupWindow) 类型_逻辑名称
item_main_song.xml主页歌曲列表项 类型_模块名_逻辑名称

 

6、Drawable命名

 

要一眼能看出它的作用,比如:shape_shadow_bottom.xml,selected_indicator_red.xml,

第一个,看命名就知道它是一个shape,它是一个阴影,并且位置在下面。

第二个,一看就知道他是一个selected,作用在指示线,颜色是红的。

如果不这样命名,drawable是非常容易出现大量重复作用的文件。

 

 

7、图片命名(drawable/ 和 mipmap/)

 

res/drawable/ 目录下放的是位图文件(.png、.9.png、.jpg、.gif)或编译为可绘制对象资源子类型的 XML 文件,而 res/mipmap/ 目录下放的是不同密度的启动图标,所以 res/mipmap/ 只用于存放启动图标,其余图片资源文件都应该放到 res/drawable/ 目录下。

命名规则:类型{_模块名}_逻辑名称类型{_模块名}_颜色

说明:{} 中的内容为可选;类型 可以是可绘制对象资源类型,也可以是控件类型(具体见附录UI 控件缩写表);最后可加后缀 _small 表示小图,_big 表示大图。

例如:

名称

说明

btn_main_about.png主页关于按键 类型_模块名_逻辑名称
btn_back.png返回按键 类型_逻辑名称
divider_maket_white.png商城白色分割线 类型_模块名_颜色
ic_edit.png编辑图标 类型_逻辑名称
bg_main.png主页背景 类型_逻辑名称
btn_red.png红色按键 类型_颜色
btn_red_big.png红色大按键 类型_颜色
ic_head_small.png小头像图标 类型_逻辑名称
bg_input.png输入框背景 类型_逻辑名称
divider_white.png白色分割线 类型_颜色
bg_main_head.png主页头部背景 类型_模块名_逻辑名称
def_search_cell.png搜索页面默认单元图片 类型_模块名_逻辑名称
ic_more_help.png更多帮助图标 类型_逻辑名称
divider_list_line.png列表分割线 类型_逻辑名称
sel_search_ok.xml搜索界面确认选择器 类型_模块名_逻辑名称
shape_music_ring.xml音乐界面环形形状 类型_模块名_逻辑名称

 

如果有多种形态,如按钮选择器:sel_btn_xx.xml,采用如下命名:

名称

说明

sel_btn_xx作用在 btn_xx 上的 selector
btn_xx_normal默认状态效果
btn_xx_pressedstate_pressed 点击效果
btn_xx_focusedstate_focused 聚焦效果
btn_xx_disabledstate_enabled 不可用效果
btn_xx_checkedstate_checked 选中效果
btn_xx_selectedstate_selected 选中效果
btn_xx_hoveredstate_hovered 悬停效果
btn_xx_checkablestate_checkable 可选效果
btn_xx_activatedstate_activated 激活效果
btn_xx_window_focusedstate_window_focused 窗口聚焦效果

 

注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector,前提是命名要规范。

 

 

8、菜单资源文件(menu/)

 

菜单相关的资源文件应放在该目录下。

命名规则:menu{_模块名}_逻辑名称

说明:{} 中的内容为可选。

例如:menu_main_drawer.xml、menu_navigation.xml

 

 

9、values资源文件(values/)

待定

 

10、动画资源文件(anim/ 和 animator/)

 

安卓主要包含属性动画和视图动画,其视图动画包括补间动画和逐帧动画。

属性动画文件需要放在 res/animator/ 目录下,

视图动画文件需放在 res/anim/ 目录下。

 

命名规则:anim_{模块名_}逻辑名称

 

说明:{} 中的内容为可选,逻辑名称 可由多个单词加下划线组成。

 

例如:anim_refresh_progress.xml、anim_market_cart_add.xml、anim_market_cart_remove.xml

 

 

如果是普通的补间动画或者属性动画,可采用:动画类型_方向 的命名方式。

 

例如:

 

名称

说明

fade_in淡入
fade_out淡出
push_down_in从下方推入
push_down_out从下方推出
push_left推向左方
slide_in_from_top从头部滑动进入
zoom_enter变形进入
slide_in滑动进入
shrink_to_middle中间缩小

 

 

11、颜色资源文件(color/)

 

专门存放颜色相关的资源文件。

 

命名规则:类型{_模块名}_逻辑名称

 

说明:{} 中的内容为可选。

 

例如:sel_btn_font.xml

 

颜色资源也可以放于 res/drawable/ 目录,引用时则用 @drawable 来引用,但不推荐这么做,最好还是把两者分开

 

12、id 命名

命名规则:view 缩写{_模块名}_逻辑名,例如: btn_main_searchbtn_back

如果在项目中有用黄油刀的话,使用 AS 的插件:ButterKnife Zelezny,可以非常方便帮助你生成注解;没用黄油刀的话可以使用 Android Code Generator 插件。

 

 

13、其它

1、插件检测(以该插件提示为准,警告的都修改过来)

请自行安装《阿里巴巴Java开发规约》插件,在(Preferences > Plugins)插件处搜索alibaba即可。

插件官方开源地址

2、开发时新功能完全依照《阿里巴巴Java开发规约》提示,老功能的话开发到的地方根据提示尽量修改过来,review时作为review通过标准之一。

 

 

(二)常量定义

代码中不要出现数字常量,如果有数字常量判断的话,需要定义出来,并增加注释说明含义

 

(三)代码格式

1、代码格式化后再上传

2、代码不要出现数字

3、接口参数或定义的常量或请求的URL等,一定要增加注释说明。即达到离开了文档也能明白这个接口是干什么的,每一个参数含义用法等,返回的参数同样。

4、if条件判断,如果只有一行代码的,请加上{},方便阅读。如果一定不想加{},请使用这种形式:if (condition) body();   

5、编写简短方法:在可行的情况下,尽量编写短小精炼的方法。我们了解,有些情况下较长的方法是恰当的,因此对方法的代码长度没有做出硬性限制。如果某个方法的代码超出 40 行,请考虑是否可以在不破坏程序结构的前提下对其拆解。

6、类的成员顺序:这并没有唯一的正确解决方案,但如果都使用一致的顺序将会提高代码的可读性,推荐使用如下排序:

  1. 常量
  2. 字段
  3. 构造函数
  4. 重写函数和回调
  5. 公有函数
  6. 私有函数
  7. 内部类或接口

如果类继承于 Android 组件(例如 Activity 或 Fragment),那么把重写函数按照他们的生命周期进行排序。

7、函数参数的排序:在 Android 开发过程中,Context 在函数参数中是再常见不过的了,我们最好把 Context 作为其第一个参数。

正相反,我们把回调接口应该作为其最后一个参数。如:public void loadUserAsync(Context context, int userId, UserCallback callback);

8、代码块和layout推荐可用块注释把代码分类开来

9、在循环中或多层级对象时,如果获取某个对象的多个某值时,把对象定义出来,再获取

如:

//推荐如下:

for(int i = 0;i < len; i++){

    Teacher teacher = list.get(i);

    teacher.getName();

    teacher.getAge();

}

//不推荐这样的写法:

for(int i = 0;i < len; i++){

    list.get(i).getName();

    list.get(i)..getAge;

}

//推荐如下:

public void showView(Teacher teacher){

    Class class teacher.getClass();

    class.getName();

    class.getAddress();

}

//不推荐这样的写法:

public void showView(Teacher teacher){

    teacher.getClass().getName();

    teacher.getClass().getAddress();

}

 

 

 

 

(四)注释风格

为了减少他人阅读你代码的痛苦值,请在关键地方做好注释。

类、方法、字段等都需要根据情况增加注释,个别容易理解的可不加。

1、类注释

每个类完成后应该有作者姓名和创建时间的注释,对自己的代码负责。

 

具体可以在 AS 中自己配制,进入 Preferences -> Editor -> File and Code Templates -> Includes -> File Header,输入模板

/**
* Created by ${USER} on ${YEAR}/${MONTH}/${DAY}.
* 请写类注释 
*/

这样便可在每次新建类的时候自动加上该头注释。

 

2、方法注释

每一个成员方法(包括自定义成员方法、覆盖方法、属性方法)的方法头都必须做方法头注释,在方法前一行输入 /** + 回车 或者设置 Fix doc comment(Preferences -> Keymap -> Fix doc comment)快捷键,AS 便会帮你生成模板,我们只需要补全参数即可

 

3、块注释

块注释与其周围的代码在同一缩进级别。它们可以是 /* ... */ 风格,也可以是 // ... 风格(// 后最好带一个空格)。

对于多行的 /* ... */ 注释,后续行必须从 * 开始, 并且与前一行的 * 对齐。

以下示例注释都是 OK 的。

/*

 * This is

 * okay.

 */

 

// And so

// is this.

 

/* Or you can

 * even do this. */

 

4、其它一些注释

AS 已帮你集成了一些注释模板,我们只需要直接使用即可,在代码中输入 todofixme 等这些注释模板,回车后便会出现如下注释。

// TODO: 2019/2/23 需要实现,但目前还未实现的功能的说明
// FIXME: 2019/2/23 需要修正,甚至代码是错误的,不能工作,需要修复的说明

 

(五)包

1、包名全部小写,连续的单词只是简单地连接起来,不使用下划线,采用反域名命名规则,全部使用小写字母

一级包名是顶级域名,通常为 comedugovnetorg 等,

二级包名为公司名,

三级包名根据应用进行命名,后面就是对包名的划分了。

 

2、包分类以及MVP风格

 

 

 

(六)、其它的一些规范

  1. 合理布局,有效运用 <merge><ViewStub><include> 标签;

  2. Activity 和 Fragment 里面有许多重复的操作以及操作步骤,所以我们都需要提供一个 BaseActivity 和 BaseFragment,让所有的 Activity 和 Fragment 都继承这个基类。

  3. 方法基本上都按照调用的先后顺序在各自区块中排列;

  4. 相关功能作为小区块放在一起(或者封装掉);

  5. 当一个类有多个构造函数,或是多个同名函数,这些函数应该按顺序出现在一起,中间不要放进其它函数;

  6. 数据提供统一的入口。无论是在 MVP、MVC 还是 MVVM 中,提供一个统一的数据入口,都可以让代码变得更加易于维护。比如可使用一个 DataManager,把 httppreferenceeventpostdatabase 都放在 DataManager 里面进行操作,我们只需要与 DataManager 打交道;

  7. 多用组合,少用继承;

  8. 提取方法,去除重复代码。对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。

  9. 可引入 Dagger2 减少模块之间的耦合性。Dagger2 是一个依赖注入框架,使用代码自动生成创建依赖关系需要的代码。减少很多模板化的代码,更易于测试,降低耦合,创建可复用可互换的模块;

  10. 项目引入 RxAndroid 响应式编程,可以极大的减少逻辑代码;

  11. 通过引入事件总线,如:EventBusAndroidEventBusRxBus,它允许我们在 DataLayer 中发送事件,以便 ViewLayer 中的多个组件都能够订阅到这些事件,减少回调;

  12. 尽可能使用局部变量;

  13. 及时关闭流;

  14. 尽量减少对变量的重复计算;

    如下面的操作:

    for (int i = 0; i < list.size(); i++) {

          ...

    }


    建议替换为:
     

    for (int i = 0, len = list.size(); i < len; i++) {

          ...

    }

  15. 尽量采用懒加载的策略,即在需要的时候才创建;
    例如:

    String str = "aaa";

    if (i == 1) {

          list.add(str);

    }

    建议替换为:

    if (i == 1) {

          String str = "aaa";

          list.add(str);

    }

  16. 不要在循环中使用 try…catch…,应该把其放在最外层;

  17. 使用带缓冲的输入输出流进行 IO 操作;

  18. 尽量使用 HashMapArrayListStringBuilder,除非线程安全需要,否则不推荐使用 HashTableVectorStringBuffer,后三者由于使用同步机制而导致了性能开销;

  19. 尽量在合适的场合使用单例;

    使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:

    1. 控制资源的使用,通过线程同步来控制资源的并发访问。

    2. 控制实例的产生,以达到节约资源的目的。

    3. 控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。

  20. 把一个基本数据类型转为字符串,基本数据类型.toString() 是最快的方式,String.valueOf(数据) 次之,数据 + "" 最慢;

  21. 使用 AS 自带的 Lint 来优化代码结构(什么,你不会?右键 module、目录或者文件,选择 Analyze -> Inspect Code);

  22. 最后不要忘了内存泄漏的检测;

  23. 禁止直接打印PB对象,打印自定义的model时,需要在对应的model自己实现toString方法,不允许打印无意义model。
  24. 单例写法推荐:(待完善)

 

二、日志添加规范

目前我们的线上日志等级E的会记录到本地文件,为了大家都能一眼看懂输出的日志,需要遵循以下规范。

统一使用HT_Log.java

(一)、开发环境

 

HT_Log.v(),HT_Log.i(),HT_Log.w(),HT_Log.d(),HT_Log.e() 都会打印并记录到本地文件

(二)、线上环境

 

HT_Log.e()会打印并记录到本地文件

(三)、打印输出规范

 

1、每个类定义一个TAG,以当前类名为内容,当作log的tag,用来区分打印是来自哪个类(可在类模板里配置)

2、Log打印内容体组成规则:方法名_逻辑名_{_参数字段名}_具体要打印的参数值(多参数时以,号分隔开)

 

 

三、Git使用规范

1、上传先首先在本地编译,看代码是否能编译通过,保证其它成员拉到的代码是可正常运行的。

2、提交前一定前先review一遍自己修改到的每一个文件,每一行代码。看是否有错改、多改的地方。

3、log内容提交规范:动作描述_模块描述_功能描述_具体修改的地方或逻辑 (如:修改信息流列表接口逻辑)

动作描述

说明

修改修改代码或文件
添加添加代码或文件
删除删除代码或文件

4、勤更新、勤提交。

5、如在合并代码时,遇到文件冲突,如不能很正确的解决冲突点,可通过查看多版本代码比较确定差异点或找到开发当事人一起合并,防止把别人有效代码给覆盖。

 

 

四、数据上报规范

待讨论

1、数据上报逻辑代码是否可与功能逻辑代码分离,方便阅读以及以后增删维护。

 

五、第三方库或大型工具类代码引入规范

 

主要目的是为了减少重复引入或选型错误问题

引入第三方库或大型工具类代码最好由Leader统一选型后引入

如必须要亲自引入的,也需要组内知会一下所有成员(可通过企业微信群)

Android 流行框架查速表

Android 开发人员不得不收集的代码

 

 

六、AS规范

 

1、尽量使用最新的稳定版的 IDE 进行开发,最好大家统一一个版本,一起升级;

2、编码格式统一为 UTF-8;

3、编辑完 .java、.xml 等文件后一定要格式化;

4、删除多余的 import,减少警告出现;

 

七、代码模板

待定

 

 

 

 

 

参考

Android开发规范

阿里巴巴Java开发手册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值