Android开发规范

来源:互联网 发布:淘宝直通车效果怎么样 编辑:程序博客网 时间:2024/06/04 18:53

为什么需要开发规范


编码规范对于程序员而言尤为重要,有以下几个原因:
1) 整个项目生命周期中,80%的时间在于维护
2) 项目很少由一个人独立完成,往往需要团队多人协作
3) 编码规范可以增强项目代码的可读性和可维护性

     如果代码命名不够规范,那么可能需要花费大量时间阅读代码去理解具体代码是干什么用的, 修改也会花费比较多的时间。如果项目始终是一个人做没问题,但如果是团队分工合作,别人再去看你的代码就更加吃力了,因为每个人之间的编程风格不一样,所以在开发过程中,有一套统一的命名规范尤为重要,最好是团队作规定,对日后维护工作会轻松很多。

开发规范的作用

1) 减少维护时间成本
2) 提高可读性
3) 加快工作交接
4) 降低缺陷引入的机会

程序员养成良好的编程习惯和代码规范,对团队降低维护成本,对个人是自身编程素养的提高。


Android代码规范之基本命名规则


为了增加程序代码在程序员之间的相互可读性,命名必须按照一定规则。
基本的原则是: 单词之间不以空格、连接号或者底线连结(例如不应写成:camel case、camel-case或camel_case形),另外要见名知义。 严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。正确的英文拼写和语法可以让阅读者易于理解,避免歧义。

两种基本的命名规则:
驼峰命名法:又称小驼峰命名法,第一个单词首字母小写,其余所有单词首字母都要大写。如:firstName、lastName等。
帕斯卡命名法:又称大驼峰命名法,每一个单词首字母大写。如:FirstName、LastName等。

Android代码规范之工程文件命名规范


1. Package Manner 包管理规范

    package name包名的规范:所有包名一律小写,不使用下划线,采用反域名命名规则。
    一级包名是顶级域名,通常为com,edu,gov,net,org等,二级包名为公司名,三级包名根据应用进行命名,后面就是对包名的划分了,
    建议规则:com.公司名.项目名.模块名 
    如:com.tianque.zhzw.xxx,一般结构不会超过3层或4层
     

    包划分要做到一点,尽量让人从目录结构上知道这个包下面的东西是干嘛用的。
    如activity下面放的都是Activity类,fragment下面放的都是Fragment类, utils下面放的都是工具类等等。
   关于包划分的规则,传统的一般是按照上图那样按照层分包(PBL, Package By Layer),很多应用都是这样做的。
   另外有一些人极力推荐按照功能(PBF, Package By Feature)进行划分:

    
    个人认为,这两种方式各有优缺点,PBL层次感更强,符合一般人正常的划分习惯(相同口味的水果放在相同的篮子里),但是功能(业务)可读性划分不强(不知道篮子里哪些水果是我的),PBF具有更高的内聚,功能上可读性强,更具模块化(我的水果放到我的篮子里,你的水果放到你的篮子里),但是破坏了层次感(我的篮子里各种口味的水果都有)。
PBL中包的大小会无限增长(因为功能越添越多,会添加越来越多的class),而PBF中包也会变的太大(包里class太多)重构需要划分更多的子包(包名会变的越来越长)。
个人推荐:
                在业务功能不是太复杂的情况下按照PBL分类,在分层的基础上如有需要再进行子包划分。
                在业务功能极为复杂的情况下按照PBF进行划分,更加侧重于复杂的业务。

2.Class files 类文件命名

   类命名方式采用大驼峰命名法,即所有单词首字母大写。  如:HelloWorldActivity。
   对于继承自安卓组件的类来说,类名应该以该组件名结尾,例如 : SignInActivity, SignInFragment ,ImageUploaderService, ChangePasswordDialog.
   对于工具类来说,命名方式应该以其完成功能开始,以 Utils 结束 ,例如 :HttpUtils , ImageUtils.
  Activity –> xxxActivity.java
  Application –> xxxApplication.java
  Fragment –> xxxFragment.java
  Service –> xxxService.java
  BroadcastReceiver –> xxxBroReceiver.java
  ContentProvider –> xxxProvider.java
  Adapter –> xxxAdapter.java
  Handler –> xxxHandler.java
  接口实现类 –> xxxImpl.java
  Persenter –> xxxPersenter.java
  公共父类 –> BaseActivity.java、BaseFragment.java、- BaseAdapter.java等
  util类 –> LogUtil.java
  数据库类 –> BaseSQLiteDBHelper.java

  •    xxx除了要首字母大写外,要尽量做到简洁而又富于描述,让别人通过名字知道其含义,做如:LoginActivity, DownloadService等

   接口(interface):命名规则与类一样采用大驼峰命名法。
   如果项目采用MVP,所有Model、View、Presenter的接口都以I为前缀,不加后缀,其他的接口采用上述命名规则。

3.Resources files 资源文件

资源文件以小写加下划线__的方式命名:用途_模块名_逻辑名称/颜色/效果

drawable 文件的命名规范
Asset TypePrefix 前缀ExampleAction barab_ab_stacked.9.pngButtonbtn_btn_send_pressed.9.pngDialogdialog_dialog_top.9.pngDividerdivider_divider_horizontal.9.pngIconic_ic_star.pngMenumenu_menu_submenu_bg.9.pngNotificationnotification_notification_bg.9.pngTabstab_tab_pressed.9.png

icons文件的命名规范
Asset TypePrefix 前缀ExampleIconsic_ic_star.pngLauncher iconsic_launcheric_launcher_calendar.pngMenu icons and Action Bar iconsic_menuic_menu_archive.pngStatus bar iconsic_stat_notifyic_stat_notify_msg.pngTab iconsic_tabic_tab_recent.pngDialog iconsic_dialogic_dialog_info.png

 选择器状态文件的命名规范
StateSuffix 尾缀ExampleNormal_normalbtn_order_normal.9.pngPressed_pressedbtn_order_pressed.9.pngFocused_focusedbtn_order_focused.9.pngDisabled_disabledbtn_order_disabled.9.pngSelected_selectedbtn_order_selected.9.png
 
  Layout files 布局文件命名规范

Component 组件Class NameLayout NameActivityUserProfileActivityactivity_user_profile.xmlFragmentSignUpFragmentfragment_sign_up.xmlDialogChangePasswordDialogdialog_change_password.xmlAdapterView Item---item_person.xml
anim动画文件命名规范
普通的tween动画采用:动画类型_方向
名称说明fade_in淡入fade_out淡出push_down_in从下方推入push_down_out从下方推出push_left推向左方slide_in_from_top从头部滑动进入zoom_enter变形进入slide_in滑动进入shrink_to_middle中间缩小

  其他:
  关于资源文件的存放,图片资源在drawable目录下存放具体哪个目录,涉及屏幕适配,这里不展开讨论,可以参考判断手机读取drawable哪一个目录下的图片 和Android屏幕适配全攻略。
  关于app应用图标,在android studio中是放在mipmap目录下的,新版当中还提供了一种圆形的图标icon。

Android代码规范之变量命名规范


java普通的变量命名规则一般采用小驼峰命名规则。

1. 全局变量

 按照驼峰规则命名,全局变量首字母以m开头(非静态),如mContext,  可以参考Google Android源码中的命名
  
 变量命名要做到足够长有一定意义,同时又足够短以避免冗长。
 关于携带Android控件的变量,个人建议规则:【控件逻辑名称】+【控件缩写】
 如mLoginBtn, mBottomLayout, mTitleText, 能用全名的可以尽量用全名不用缩写如mLoginButton,
 但绝对不要写成mDialog1, mDialog2, mBtn1, mBtn2等等这样的。命名要做到见名知义。

2. 局部变量

  局部变量也是按照驼峰规则命名,前面不用加m, 如loginBtn,resultString,loginPresenter,
  不能有下划线之类的如myname_text, btn_commit。命名要做到见名知义。
  尽量用简洁的单词描述,但是避免单个字符如a, b,i,j, 除非是临时变量循环变量在for循环中使用。 
   
 常见单词的缩写:
单词缩写iconicbackgroundbgforegroundfginitialinitinformationinfosuccesssuccfailurefailerrorerrimageimglibrarylibmessagemsgpasswordpwdlengthlenbufferbufpositionpos

能用全称的尽量用全称不用缩写。另外缩写尽量不要使用拼音和英文及数字混拼。

3. 静态变量/常量

   不同于前两种,静态常量(static/final)一般应该全部大写,中间用下划线分开。命名要做到见名知义。
    

4. 方法名

    采用驼峰命名规则。首单词首字母小写,其余单词首字母大写。尽量不要使用下划线。
     命名要做到见名知义。函数名如果过长,部分常见单词可以采用缩写表示。
     
     方法名通常是动词或动词短语。 
方法说明initXX()初始化相关方法,使用init为前缀标识,如初始化布局initView()isXX() checkXX()方法返回值为boolean型的请使用is或check为前缀标识getXX()返回某个值的方法,使用get为前缀标识setXX()设置某个属性值handleXX()/processXX()对数据进行处理的方法displayXX()/showXX()弹出提示框和提示信息,使用display/show为前缀标识updateXX()更新数据saveXX()保存数据resetXX()重置数据clearXX()清除数据removeXX()移除数据或者视图等,如removeView();drawXX()绘制数据或效果相关的,使用draw前缀标识

5. 控件Id

    全部采用小写,单词之间使用下划线分割。命名要做到见名知义。避免btn1, btn2, mynametextview这样的。
    个人建议xml中的资源id命名规则以:【控件缩写】+【控件逻辑名称】(跟代码中反过来)为主,
     例:
  •     btn_login
  •     edit_accout
  •     iv_message
  •     lv_news

 常用控件的缩写
控件布局文件中缩写代码中缩写LinearLayoutll_xxxxxxLay或xxxLayoutRelativeLayoutrl_xxxxxxRLayoutFrameLayoutfl_xxxxxxFLayoutTextViewtv_xxxxxxTv或xxxTextViewEditTextedit_xxxxxxEt或xxxEditButtonbtn_xxxxxxBtn或xxxButtonImageViewiv_xxxxxxIv或xxxImgCheckBoxchk_xxxxxxChk或xxxCheckBoxRadioButtonrbtn_xxx
xxxRbtn或xxxRadioButton
ProgressBarpbar_xxxxxxPbar或xxxProgressBarListViewlv_xxx
xxxLv或xxxListView
WebViewwv_xxx
xxxWv或xxxWebView
GridViewgv_xxx
xxxGv或xxxGridView

6. strings.xml dimens.xml colors.xml等变量命名

 strings.xml
 strings的name命名使用下划线命名法,采用以下规则:模块名+逻辑名称,这样方便同一个界面的所有string都放到一起,方便查找。
名称说明main_menu_about主菜单按键文字friend_title好友模块标题栏friend_dialog_del好友删除提示login_check_email登录验证dialog_title弹出框标题button_ok确认键loading加载文字
colors.xml
colors.xml的name命名使用下划线命名法,在你的colors.xml文件中应该只是映射颜色的名称一个ARGB值,而没有其它的。
不要使用它为不同的按钮来定义ARGB值。

不要这样做

  <resources>      <color name="button_foreground">#FFFFFF</color>      <color name="button_background">#2A91BD</color>      <color name="comment_background_inactive">#5F5F5F</color>      <color name="comment_background_active">#939393</color>      <color name="comment_foreground">#FFFFFF</color>      <color name="comment_foreground_important">#FF9D2F</color>      ...      <color name="comment_shadow">#323232</color>
使用这种格式,你会非常容易的开始重复定义ARGB值,这使如果需要改变基本色变的很复杂。
同时,这些定义是跟一些环境关联起来的,如button,应该放到一个按钮风格中,而不是在colors.xml文件中。

相反,这样做

  <resources>      <!-- grayscale -->      <color name="white"     >#FFFFFF</color>      <color name="gray_light">#DBDBDB</color>      <color name="gray"      >#939393</color>      <color name="gray_dark" >#5F5F5F</color>      <color name="black"     >#323232</color>      <!-- basic colors -->      <color name="green">#27D34D</color>      <color name="blue">#2A91BD</color>      <color name="orange">#FF9D2F</color>      <color name="red">#FF432F</color>  </resources>
 像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。
 通常一个具有审美价值的UI来说,减少使用颜色的种类是非常重要的。
 注意:如果某些颜色和主题有关,那就单独写一个colors_theme.xml

dimens.xml
像对待colors.xml一样对待dimens.xml文件,dimens命名应该按照一套统一的规则。 一个好的例子:
<resources>

    <!-- font sizes -->
    <dimen name="font_22">22sp</dimen>
    <dimen name="font_18">18sp</dimen>
    <dimen name="font_15">15sp</dimen>
    <dimen name="font_12">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_40">40dp</dimen>
    <dimen name="spacing_24">24dp</dimen>
    <dimen name="spacing_14">14dp</dimen>
    <dimen name="spacing_10">10dp</dimen>
    <dimen name="spacing_4">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_60">60dp</dimen>
    <dimen name="button_height_40">40dp</dimen>
    <dimen name="button_height_32">32dp</dimen>

</resources>
布局时需要尺寸大小时进行引用,像这样规范的尺寸很容易修改或重构,会使应用所有用到的尺寸一目了然,会使组织和改变风格或布局是非常容易。

styles.xml
style的name命名使用大驼峰命名法。几乎每个项目都需要适当的使用style文件,因为对于一个视图来说有一个重复的外观是很常见的。
将所有的外观细节属性(colors、padding、font)放在style文件中。 在应用中对于大多数文本内容,最起码你应该有一个通用的style文件,例如:
<style name="ContentText">    <item name="android:textSize">@dimen/font_normal</item>    <item name="android:textColor">@color/basic_black</item></style>
应用到TextView中:
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />
需要为控件做重复的事情时,可以将重复的属性放到通用的style中。

Android代码规范之代码样式规范


Android开发代码样式(format)一般按照Google默认提供的格式:


可以在settings设置中去修改,但一般我们不做修改,统一用默认的样式即可。除非有特殊要求。

一些需要注意的:

1. 大括号

大括号与if, else, for, do, while语句一起使用,即使只有一条语句(或是空),也应该把大括号写上。

2. 非空块:K & R 风格

对于非空块和块状结构,大括号遵循 Kernighan 和 Ritchie 风格 (Egyptian brackets):
  • 左大括号前不换行
  • 左大括号后换行
  • 右大括号前换行
  • 如果右大括号是一个语句、函数体或类的终止,则右大括号后换行; 否则不换行。
例如,如果右大括号后面是else或逗号,则不换行。
示例:
 new MyClass() {       @Override public void method() {               if (condition()) {            try {                something();            } catch (ProblemException e) {                recover();            }        }    } };

3.一行一个语句

每个语句后要换行。

4.块缩进:4个空格

每当开始一个新的块,缩进增加4个空格,当块结束时,缩进返回先前的缩进级别。缩进级别适用于代码和注释。
最好使用4个空格代替Tab,在不同的编译环境中,Tab所表示的长度可能不一致。

5.自动换行

术语说明:一般情况下,一行长代码为了避免超出列限制(80或100个字符)而被分为多行,我们称之为自动换行(line-wrapping)。
我们并没有全面,确定性的准则来决定在每一种情况下如何自动换行。很多时候,对于同一段代码会有好几种有效的自动换行方式。
从哪里断开:
自动换行的基本准则是:更倾向于在更高的语法级别处断开。
  1. 如果在非赋值运算符处断开,那么在该符号前断开(比如+,它将位于下一行)。
  2. 这条规则也适用于以下"类运算符"符号:点分隔符(.),类型界限中的 &(),catch 块中的catch符号。
  3. 如果在赋值运算符处断开,通常的做法是在该符号后断开(比如=,它与前面的内容留在同一行)。
  4. 方法名或构造函数名与左括号留在同一行。
  5. 逗号(,)与其前面的内容留在同一行。

6.空行

以下情况需要使用一个空行:
  1. 类内连续的成员之间:字段,构造函数,方法,嵌套类,静态初始化块,实例初始化块。 例外: 两个连续字段之间的空行是可选的,用于字段的空行主要用来对字段进行逻辑分组。
  2. 在函数体内,语句的逻辑分组间使用空行。
  3. 多个连续的空行是允许的,但没有必要这样做(我们也不鼓励这样做)。

7.空格

以下情况需要使用一个空格:

  1. 分隔任何保留字与紧随其后的左括号(()(如if, for catch等)。
  2. 分隔任何保留字与其前面的右大括号(})(如else, catch)。
  3. 在任何左大括号前({),两个例外:
    o @SomeAnnotation({a, b})(不使用空格)。
    o String[][] x = foo;(大括号间没有空格)。
  4. 在任何二元或三元运算符的两侧。这也适用于以下"类运算符"符号:
    o 类型界限中的&()。
    o catch块中的管道符号(catch (FooException | BarException e)。
    o foreach语句中的分号。
  5. 在, : ;及右括号())后
  6. 如果在一条语句后做注释,则双斜杠(//)两边都要空格。这里可以允许多个空格,但没有必要。
  7. 类型和变量之间:List list。
  8. 数组初始化中,大括号内的空格是可选的,即new int[] {5, 6}和new int[] { 5, 6 }都是可以的。

8.每次只声明一个变量

不要推荐使用组合声明,比如int a, b;。如非必须,变量在需要的时候才去声明并初始化。

9.方法参数不宜过多

如果方法参数太多,函数声明方法名会很长,可以考虑用实体类来封装参数。

10.方法中的行数不宜过多

如果方法长度没有统一标准规定,因为有的方法确实会很长,但是一般来说当方法长度超过50行左右,可以考虑优化进行方法提取(refactor)。

例如最常见的在Activity的onCreate方法中写过长的代码:
不要这样做


相反,这样做

是不是简洁清晰了很多

Android代码规范之代码注释


好的代码需要一套规范的注释方法
1) 一个工程应有一个统一的头文件注释,以说明整个工程的信息、创建日期、版本等等
2) 对重要的程序必须加注释进行说明
3) 修改代码或删除时,将原代码用注释的方法屏蔽,同时要加开发者自身对修改操作的注释
4) 移除所有临时或无关的注释,以避免在日后的维护工作中产生混乱
5) 注释应对代码进行准确的说明,不应存在歧义

1. 类注释

   原则上编写完成每个类都要有一个头部注释,标注类的功能描述,作者,联系方式和修改日期等。对自己的代码负责。

头部注释的添加有两种方式:
第一种方式,可以在AS中,Settings → Editor → File and Code Templates → Includes → File Header,输入:
 /**
 * 描述:添加类的描述
 * @anthor $(USER)
 * @e-mail XXX@XX.com
 * @time   ${DATE}
 */
 
这样便可在每次新建类的时候自动加上该头注释。
  
 第二种方式,在Settings → Editor → Live Templates中配置,
 详情参考:http://www.cnblogs.com/zgz345/p/4994885.html
                    http://blog.csdn.net/pkandroid/article/details/52686199
 这种方式是配置模板和对应的快捷键,比如我的配置完成后在类的开头输入lf回车就会自动生成对应的注释模板:
       
 相比第一种而言,不会每个类新建都生成,只有需要的时候再手动添加,更加灵活。

2. 方法注释

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

3. 块注释

块注释是最常用的注释,它与其周围的代码在同一缩进级别。
它们可以是/* ... */风格,也可以是// ...风格(//后最好带一个空格)。
对于多行的/* ... */注释,后续行必须从*开始, 并且与前一行的*对齐。


一般我们还会注释掉代码,修改代码或删除时,将原代码用注释的方法屏蔽,同时要加开发者自身对修改操作的注释。


3. TODO注释

   当你需要后续再对代码进行补充修改时,可以使用todo模板注释, 在代码中输入todo、fixme等这些注释模板,然后回车,
   AS会自动帮你生成如下注释:
   

   要查找之前哪些todo没有完成,可以在AS左下角todo面板中很方便的找到,AS会将你所有的todo项列出:
   
   喜欢这个功能的可以看看这篇文章:玩转自定义TODO

4. XML注释

     在XML文档中,使用如下面格式注释:
    <!-- 注释内容 -->
    
   其他:配置文件或mk文件等可使用#进行注释。

Android代码规范之Log开关


在代码合适的地方添加Log输出,一般情况下我们的需求是希望debug状态下的输出log, 而release的包不希望输出log。一般我们在整个应用中应该使用和建立一个统一全局的Log开关类,方便统一开关管理。
    可以定义自己的boolean变量来控制开关,这里介绍利用AS的BuildConfig.DEBUG属性来控制是否输出log, gradle在编译debug包的时候BuildConfig类的DEBUG变量自动为true, 而编译release包的时候自动为false, 利用这点就可以实现在打debug包会自动输出log, 而release包的时候不会输出log。


使用的时候无需关心当前debug状态:

即便代码里到处都是TQLog调用也没关系,因为release编译的时候Log会自动编译,只会在debug时才有输出。
另外,也可以在gradle中为BuildConfig添加自己的变量来控制log开关:

则代码中的log开关换成下面这句即可:


BuildConfig文件(自动生成在/build/generated/source/buildConfig/目录下)

PS:关于BuildConfig,AS里有一个坑,AS中依赖的module默认是 release状态的,所以BuildConfig的DEBUG总是false,
   详情看这里:解决依赖 library module的BuildConfig 坑(重构项目中我按照此方案解决)