安卓开发规范

安卓开发规范笔录

前言

提高产品质量,提高开发效率,以及提升个人能力,故形成此规范。该文档的目的是约束各类不同“风格”并使其规范化、标准化,进行规范编码。
好了说完这些冠冕堂皇的辞藻,转入正常的表述了,作为码农界一个辛勤的搬运工,定是要把各大家之优秀集成于一家,在参考了阿里巴巴开发规范(为码农界做了一大贡献啊,给他点个赞!)以及网上各安卓开发规范零星规范后得出此规范。由于不大会使用这个编辑工具,有点难看,不喜勿喷,仅做笔记使用。
阅读说明,标注【强制】为必须按照此规则进行编写,否则所编写的代码则为不符规范。标注【推荐】为强烈推荐按照该规则进行编写,标注【参考】为如果可以则应该按照该规则进行编写。

目录

前言:
命名规范
Java命名规范
变量定义规范
布局资源文件命名规范
动画资源命名
资源ID命名
包名命名规范
常见英文单词缩写
编写规范
代码区块划分
类成员排列通用规则
注释规范
编程规范
安卓编程规范
安卓字符串常量的命名和值
Activities 和 Fragments 的传参
并发处理
异常处理
日志规约

AS设置

【强制】必须使用UTF-8字符集
【推荐】建议设置代码行长120(AS默认为100),符合我们的显示器(1600*900)大小。

命名规范

Java命名规范
1.【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。
正例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。
反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3

2.【强制】类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO 正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion 反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
3.【强制】方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。 正例: localValue / getHttpMessage() / inputUserId
4、【推荐】方法命名例举:
方法说明initXX()初始化相关方法,使用init为前缀标识,如初始化布局initView()isXX() checkXX()方法返回值为boolean型的请使用is或check为前缀标识getXX()返回某个值的方法,使用get为前缀标识handleXX()对数据进行处理的方法,尽量使用handle为前缀标识displayXX()/showXX()弹出提示框和提示信息,使用display/show为前缀标识saveXX()与保存数据相关的,使用save为前缀标识resetXX()对数据重组的,使用reset前缀标识clearXX()清除数据相关的removeXXX()清除数据相关的drawXXX()绘制数据或效果相关的,使用draw前缀标识

5.【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT反例:MAX_COU
6.【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
7.【强制】类名命名方式。名词,采用大驼峰命名法,尽量避免缩写,除非该缩写是众所周知的, 比如HTML,URL,如果类名称中包含单词缩写,则单词缩写的每个字母均应大写。
类描述例如Activity 类Activity为后缀标识欢迎页面类WelcomeActivityAdapter类Adapter 为后缀标识新闻详情适配器 NewDetailAdapter解析类Parser为后缀标识首页解析类HomePosterParser工具方法类Util或Manager为后缀标识(与系统或第三方的Utils区分)或功能+Util。(最常用的日志工具类除外:L)线程池管理ThreadPoolManager
压缩工具类:ZipUtil数据库类以DBHelper后缀标识新闻数据库:NewDBHelperService类以Service为后缀标识时间服务TimeServiceBroadcastReceiver类以Receiver为后缀标识推送接收JPushReceiverContentProvider以Provider为后缀标识自定义的共享基础类以Base开头BaseActivity,BaseFragment

例如:HashTest 或 HashIntegrationTest。
8.【强制】接口(interface):命名规则与类一样采用大驼峰命名法,多以able或ible结尾,如
interface Runnable ;
interface Accessible;

9.【强制】中括号是数组类型的一部分,数组定义如下:String[] args;反例:使用 String args[]的方式来定义。
10.【强制】POJO 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异
11.【强制】private/public修饰词不能随便使用,默认为private,禁止非公开静态方法使用public修饰

变量定义规范

1.【强制】不允许任何魔法值(即未经定义的常量)直接出现在代码中。 反例:String key = “Id#taobao_” + tradeId; cache.put(key, value);

2.【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。
1)【推荐】跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下。
2)【推荐】应用内共享常量:放置在一方库中,通常是modules中的constant目录下。
反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义了表示“是”的变量: 类A中:public static final String YES = “yes”; 类B中:public static final String YES = “y”; A.YES.equals(B.YES),预期是true,但实际返回为false,导致线上问题。
3)【推荐】子工程内部共享常量:即在当前子工程的constant目录下。
4)【推荐】包内共享常量:即在当前包下单独的constant目录下。
类内共享常量:直接在类内部private static final定义。
5)【推荐】Android SDK 中的很多类都用到了键值对函数,比如SharedPreferences、Bundle、Intent,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。当时用到这些类的时候,我们 必须 将它们的键定义为 static final 字段,并遵循以下指示作为前缀。

类字段名前缀SharedPreferencesPREF_BundleBUNDLE_Fragment ArgumentsARGUMENT_Intent ExtraEXTRA_Intent ActionACTION_
例如:
// 注意:字段的值与名称相同以避免重复问题
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”;

6)【推荐】Activities 和 Fragments 的传参
当 Activity 或 Fragment 传递数据通过 Intent 或 Bundle 时,不同值的键须遵循上一条所提及到的。
当 Activity 或 Fragment 启动需要传递参数时,那么它需要提供一个 public static 的函数来帮助启动或创建它。
public static void start(Context context, User user) {
Intent starter = new Intent(context, MainActivity.class);
starter.putParcelableExtra(EXTRA_USER, user);
context.startActivity(starter);
}
同理,启动相关 Fragment 在其内部输入 newInstance 即可,如下所示:
public static MainFragment newInstance(User user) {
Bundle args = new Bundle();
args.putParcelable(ARGUMENT_USER, user);
MainFragment fragment = new MainFragment();
fragment.setArguments(args);
return fragment;
}
注意:这些函数需要放在 onCreate() 之前的类的顶部;如果我们使用了这种方式,那么 extras 和 arguments 的键应该是 private 的,因为它们不再需要暴露给其他类来使用。

5.【推荐】如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面正例中的数字就是延伸信息,表示星期几。
正例:

public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6),
SUNDAY(7)

6.【推荐】集合添加如下后缀:List、Map、Set
7.【推荐】数组添加如下后缀:Arr
8.【推荐】量词变量后缀
First 一组变量中的第一个
Last 一组变量中的最后一个
Next 一组变量中的下一个变量
Prev 一组变量中的上一个
Cur 一组变量中的当前变量。
例如:mCustomerStrFirst mCustomerStrLast
9.【推荐】临时变量
1)、临时变量通常被取名为i,j,k,m和n,它们一般用于整型;
2)、c,d,e,它们一般用于字符型;
10.【推荐】非公有,非静态全局变量字段命名以 m 开头,其他字段以小写字母开头。
布局资源文件命名规范
1. 【推荐】资源布局文件(XML文件(layout布局文件)):
全部小写,采用下划线命名法
1) .【强制】 contentview 命名必须以全部单词小写,单词间以下划线分割,使用名词或名词词组。
所有Activity或Fragment的contentView必须与其类名对应,对应规则为:
将所有字母都转为小写,将类型和功能调换(也就是后缀变前缀)。
例如:activity_main.xml
2)【推荐】 Dialog命名:dialog_描述.xml

例如:dialog_hint.xml

3)【推荐】PopupWindow命名:ppw_描述.xml

例如:ppw_info.xml

4)【推荐】列表项命名:item_描述.xml

例如:item_city.xml

5)【推荐】包含项命名:模块_(位置)描述.xml

例如:activity_main_head.xml、activity_main_bottom.xml

注意:通用的包含项命名采用:项目名称缩写_描述.xml

例如:xxxx_title.xml
包含项命名:模块_(位置).xml
· 位置:top、 btm、 left、 right
· 例如:activity_main_btm.xml、fragment_main_top.xml
· 通用的包含项命名采用:base_(位置)项目名称缩写描述.xml
· 描述:title、 content、 header、 footer
· 例如:base_top_xxxx_title.xml、base_btm_xxxx_header.xml
· 例如:全项目通用 base_top.xml base_btm.xml

  1. 【推荐】资源文件(图片drawable文件夹下):

全部小写,采用下划线命名法,加前缀区分

命名模式:可加后缀 _small 表示小图, _big 表示大图,逻辑名称可由多个单词加下划线组成,采用以下规则:
用途模块名逻辑名称btn_main_home.png按键用途模块名颜色divider_maket_white.png 白色分割线用途逻辑名称ic_edit.png 图标用途颜色btn_red.png 红色按键

例如:
如果有多种形态如按钮等除外如 btn_xx.xml(selector)
用途模块名逻辑 名称 btn_main_home.png 按键
用途模块名颜色 divider_maket_white.png 白色分割线
用途_逻辑名称 ic_edit.png 图标
用途_颜色 btn_red.png 红色按键
动画资源命名(anim文件夹下)
全部小写,采用下划线命名法,加前缀区分。
具体动画采用以下规则:
模块名_逻辑名称
逻辑名称
refresh_progress.xml
market_cart_add.xml
market_cart_remove.xml
普通的tween动画采用如下表格中的命名方式
// 前面为动画的类型,后面为方向
动画命名例子规范写法fade_in淡入fade_out淡出push_down_in从下方推入push_down_out从下方推出push_left推向左方slide_in_from_top从头部滑动进入zoom_enter变形进入slide_in滑动进入shrink_to_middle中间缩小

资源ID命名

资源ID(resourcesid):大小写规范与方法名一致,采用小驼峰命名法。命名规范为“资源控件的缩写名”+“变量名”。注意:页面控件名称应该和控件id名保持一致,strings.xml,colors.xml等中的id命名:
命名模式为:view缩写_模块名称_view的逻辑名称
3.【推荐】控件缩写表
控件缩写例子
LinearLayoutl llFriend或者mFriendLL
RelativeLayoutr lrlMessage或mMessage
RLFrameLayoutf flCart或mCartFL
TableLayoutt l tlTab或mTabTL
Button tnbtnHome或mHomeBtnImageButtonibtnibtnPlay或mPlayIBtnRadioButton rbtn TextViewtvtvName或mNameTVEditTextetetName或mNameETListViewlvlvCart或mCartLVImageViewivivHead或mHeadIVGridViewgvgvPhoto或mPhotoGV

控件缩写CheckBox chkanalogClock anaClkDigtalClock dgtClkDatePicker dtPkTimePicker tmPktoggleButton tglBtnProgressBar proBarSeekBar skBarAutoCompleteTextViewautoTxtZoomControls zmCtlVideoView vdoViWdbView webViRantingBar ratBarTab tabSpinner spnChronometer cmtScollView sclViTextSwitch txtSwtImageSwitch imgSwtlistView lVi 或则lvExpandableList epdLtMapView mapVi

包名命名规范

1、【推荐】包名全部小写,连续的单词只是简单地连接起来,不使用下划线。
推荐使用按功能分包(Package By Feature)方式。
例如:cn.com.cookoo.kitchen
包名此包中包含com.xx.应用功能名称缩写.activity页面用到的Activity类 (activitie层级名用户界面层)com.xx.应用功能名称缩写.base基础共享的类com.xx.应用功能名称缩写.adapter页面用到的Adapter类 (适配器的类)com.xx.应用功能名称缩写.util此包中包含:公共工具方法类(util模块名)com.xx.应用功能名称缩写.bean下面可分:vo、po、dto 此包中包含:JavaBean类com.xx.应用功能名称缩写.model此包中包含:模型类com.xx.应用功能名称缩写.db数据库操作类com.xx.应用功能名称缩写.view (或者 com.xx.应用功能名称缩写.widget )自定义的View类等com.xx.应用功能名称缩写.serviceService服务com.xx.应用功能名称缩写.receiverBroadcastReceiver服务

注意:
如果项目采用MVP,所有M、V、P抽取出来的接口都放置在相应模块的i包下,所有的实现都放置在相应模块的impl下
常见英文单词缩写
名称缩写iconic (主要用在app的图标)colorcl(主要用于颜色值)dividerdi(主要用于分隔线,不仅包括Listview中的divider,还包括普通布局中的线)selectorsl(主要用于某一view多种状态,不仅包括Listview中的selector,还包括按钮的selector)averageavgbackgroundbg(主要用于布局和子布局的背景)bufferbuf 缓冲controlctrldeletedeldocumentdocerrorerrescapeescincrementinc 增量infomationinfoinitialinitimageimgInternationalizationI18N 国际化lengthlenlibrarylibmessagemsgpasswordpwdpositionposserversrvstringstrtemptmpwindowwnd(win)

编写规范

  1. 【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果是非空代码块则:
    1) 左大括号前不换行。
    2) 左大括号后换行。
    3) 右大括号前换行。
    4) 右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。
  2. 【强制】 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。详见第5条下方正例提示。
    反例:if (空格a == b空格)
  3. 【强制】if/for/while/switch/do等保留字与括号之间都必须加空格。
  4. 【强制】任何二目、三目运算符的左右两边都需要加一个空格。 说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
  5. 【强制】采用4个空格缩进,禁止使用tab字符。
    说明:如果使用tab缩进,必须设置1个tab为4个空格。IDEA设置tab为4个空格时,请勿勾选Use tab character;而在eclipse中,必须勾选insert spaces for tabs。
    正例: (涉及1-5点)
    public static void main(String[] args) {
    // 缩进4个空格
    String say = “hello”;
    // 运算符的左右必须有一个空格
    // 关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格
    if (flag == 0) {
    System.out.println(say);
    }
    // 左大括号前加空格且不换行;左大括号后换行
    if (flag == 1) {
    System.out.println(“world”);
    // 右大括号前换行,右大括号后有else,不用换行
    } else {
    System.out.println(“ok”);
    // 在右大括号后直接结束,则必须换行
    }
    }
  6. 【强制】注释的双斜线与注释内容之间有且仅有一个空格。
    正例:// 注释内容,注意在//和注释内容之间有一个空格。
  7. 【强制】单行字符数限制不超过120个,超出需要换行,换行时遵循如下原则:
    1)第二行相对第一行缩进4个空格,从第三行开始,不再继续缩进,参考示例。
    2) 运算符与下文一起换行。
    3) 方法调用的点符号与下文一起换行。
    4) 方法调用时,多个参数,需要换行时,在逗号后进行。
    5) 在括号前不要换行,见反例。
    正例:
    StringBuffer sb = new StringBuffer();
    // 超过120个字符的情况下,换行缩进4个空格,点号和方法名称一起换行
    sb.append(“zi”).append(“xin”)…
    .append(“huang”)…
    .append(“huang”)…
    .append(“huang”);
    反例:
    StringBuffer sb = new StringBuffer();
    // 超过120个字符的情况下,不要在括号前换行
    sb.append(“zi”).append(“xin”)…append
    (“huang”);
    // 参数很多的方法调用可能超过120个字符,不要在逗号前换行
    method(args1, args2, args3, …
    , argsX);
    【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。 正例:下例中实参的”a”,后边必须要有一个空格。
    method(“a”, “b”, “c”);
  8. 【强制】IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用Windows格式。
  9. 【推荐】没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。 正例:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();
说明:增加sb这个变量,如果需要对齐,则给a、b、c都要增加几个空格,在变量比较多的情况下,是一种累赘的事情。
11. 【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。 说明:没有必要插入多个空行进行隔开。

代码区块划分

【参考】使用注释将源文件分为明显的区块,区块划分如下:
1. 常量声明区
2. UI控件成员变量声明区
3. 普通成员变量声明区
4. 内部接口声明区
5. 初始化相关方法区
6. 事件响应方法区
7. 普通逻辑方法区
8. 重载的逻辑方法区
9. 发起异步任务方法区
10.异步任务回调方法区
11.生命周期回调方法区(除出去onCreate()方法)
12.内部类声明区
类成员排列通用规则
1. 按照发生的先后顺序排列
2. 常量按照使用先后排列
3. UI控件成员变量按照layout文件中的先后顺序排列
4. 普通成员变量按照使用的先后顺序排列
5. 方法基本上都按照调用的先后顺序在各自区块中排列
6. 相关功能作为小区块放在一起(或者封装掉)

注释规范

  1. 【强制】类、类属性、类方法的注释必须使用Javadoc规范,使用/*内容/格式,不得使用// xxx方式。 说明:在IDE编辑窗口中,Javadoc方式会提示相关注释,生成Javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。
  2. 【强制】所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。 说明:对子类的实现要求,或者调用注意事项,请一并说明。
  3. 【强制】所有的类都必须添加创建者和创建日期。
  4. 【强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
  5. 【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。
  6. 【推荐】与其“半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可。 反例:“TCP连接超时”解释成“传输控制协议连接超时”,理解反而费脑筋。
  7. 【推荐】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。 说明:代码与注释更新不同步,就像路网与导航软件更新不同步一样,如果导航软件严重滞后,就失去了导航的意义。
  8. 【参考】谨慎注释掉代码。在上方详细说明,而不是简单的注释掉。如果无用,则删除。 说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。
  9. 【参考】对于注释的要求:第一、能够准确反应设计思想和代码逻辑;第二、能够描述业务含义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路;注释也是给继任者看的,使其能够快速接替自己的工作。
  10. 【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。 反例:
    // put elephant into fridge
    put(elephant, fridge);
    方法名put,加上两个有意义的变量名elephant和fridge,已经说明了这是在干什么,语义清晰的代码不需要额外的注释。
  11. 【参考】特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描,经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。 1) 待办事宜(TODO):( 标记人,标记时间,[预计处理时间]) 表示需要实现,但目前还未实现的功能。这实际上是一个Javadoc的标签,目前的Javadoc还没有实现,但已经被广泛使用。只能应用于类,接口和方法(因为它是一个Javadoc标签)。 2) 错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间]) 在注释中用FIXME标记某代码是错误的,而且不能工作,需要及时纠正的情况。

12、【强制】无用的功能代码必须清除掉或者必须加上明确的注释

编程规范

安卓编程规范

【强制】1、所有的UI操作都不能在非UI线程中操作!
【强制】2、所有的网络(包含远程soket通信)操作必须放在非UI线程里操作!
【强制】3、Activity/service退出后必须显式释放相关资源。不允许存在对Activity的其他引用导致其占用内存并可能存在内存泄漏的风险。比如注册相关的回调未反注册以及handle的处理不当。
【推荐】4、在AndroidManifest.xml中注册广播时,不能在广播里做耗时/耗CPU操作,因为其是在主线程中处理,如需要长时间响应广播动作则需开启新的线程或者启动新的服务里处理;另外,如需控制BroadcastReceiver生命周期可考虑动态注册广播,动态注册的广播可控制其对象的生命周期来控制广播的生命周期;
【参考】5、广播通信会存在延时风险,故开机期间的及时通信不建议使用广播方式进行。如是进程之间需及时通信可考虑使用ContentProvider/Messenger/AIDL等方式;

【推荐】6、一个Activity包含大量的界面时,建议使用Fragment保证各视图之间逻辑清晰视图明了。
【推荐】资源自适应
【强制】国际化 必须要考虑至少中英文切换。

安卓字符串常量的命名和值

【推荐】Android SDK 中的很多类都用到了键值对函数,比如SharedPreferences、Bundle、Intent,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。当时用到这些类的时候,我们 必须 将它们的键定义为 static final 字段,并遵循以下指示作为前缀。

类字段名前缀SharedPreferencesPREF_BundleBUNDLE_Fragment ArgumentsARGUMENT_Intent ExtraEXTRA_Intent ActionACTION_
例如:
// 注意:字段的值与名称相同以避免重复问题
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”;

Activities 和 Fragments 的传参
当 Activity 或 Fragment 传递数据通过 Intent 或 Bundle 时,不同值的键须遵循上一条所提及到的。
当 Activity 或 Fragment 启动需要传递参数时,那么它需要提供一个 public static 的函数来帮助启动或创建它。
public static void start(Context context, User user) {
Intent starter = new Intent(context, MainActivity.class);
starter.putParcelableExtra(EXTRA_USER, user);
context.startActivity(starter);
}

同理,启动相关 Fragment 在其内部输入 newInstance 即可,如下所示:
public static MainFragment newInstance(User user) {
Bundle args = new Bundle();
args.putParcelable(ARGUMENT_USER, user);
MainFragment fragment = new MainFragment();
fragment.setArguments(args);
return fragment;
}

注意:这些函数需要放在 onCreate() 之前的类的顶部;如果我们使用了这种方式,那么 extras 和 arguments 的键应该是 private 的,因为它们不再需要暴露给其他类来使用。
并发处理
1. 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 说明:资源驱动类、工具类、单例工厂类都需要注意。
2. 【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。 正例:
public class TimerTaskThread extends Thread {
public TimerTaskThread() {
super.setName(“TimerTaskThread”);

}
5. 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(“yyyy-MM-dd”);
}
};
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。
6. 【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用RPC方法。
9. 【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
10. 【推荐】使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法被执行到,避免主线程无法执行至await方法,直到超时才返回结果。 说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。
11. 【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。

说明:Random实例包括java.util.Random 的实例或者 Math.random()的方式。 正例:在JDK7之后,可以直接使用API ThreadLocalRandom,而在 JDK7之前,需要编码保证每个线程持有一个实例。
12. 【推荐】在并发场景下,通过双重检查锁(double-checked locking)实现延迟初始化的优化问题隐患(可参考 The “Double-Checked Locking is Broken” Declaration),推荐解决方案中较为简单一种(适用于JDK5及以上版本),将目标属性声明为 volatile型。 反例:

class Singleton {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) synchronized(this) {
if (helper == null)
helper = new Helper();
}
return helper;
}
// other methods and fields…
}
13. 【参考】volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。如果是count++操作,使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。
14. 【参考】 HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险。
15. 【参考】ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享此静态变量 ,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只要是这个线程内定义的)都可以操控这个变量。

异常处理

  1. 【强制】不要捕获Java类库中定义的继承自RuntimeException的运行时异常类,如:IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。
    正例:if(obj!= null) {…}
    反例:try { obj.method() } catch(NullPointerException e){…}
  2. 【强制】异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。
  3. 【强制】对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。
  4. 【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
  5. 【强制】有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回滚事务。
  6. 【强制】finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。
    说明:如果JDK7,可以使用try-with-resources方法。
  7. 【强制】不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
  8. 【强制】捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
    说明:如果预期抛的是绣球,实际接到的是铅球,就会产生意外情况。
  9. 【推荐】方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回null值。调用方需要进行null判断防止NPE问题。
    说明:本规约明确防止NPE是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败,运行时异常等场景返回null的情况。
    10.【推荐】防止NPE,是程序员的基本修养,注意NPE产生的场景:
    1) 返回类型为包装数据类型,有可能是null,返回int值时注意判空。
    反例:public int f(){ returnInteger对象},如果为null,自动解箱抛NPE。
    2) 数据库的查询结果可能为null。
    3) 集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
    4) 远程调用返回对象,一律要求进行NPE判断。
    5) 对于Session中获取的数据,建议NPE检查,避免空指针。
    6) 级联调用obj.getA().getB().getC();一连串调用,易产生NPE。
    11.【推荐】在代码中使用“抛异常”还是“返回错误码”,对于公司外的http/api开放接口必须使用“错误码”;而应用内部推荐异常抛出;跨应用间RPC调用优先考虑使用Result方式,封装isSuccess、“错误码”、“错误简短信息”。
    说明:关于RPC方法返回方式使用Result方式的理由:
    1)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
    2)如果不加栈信息,只是new自定义异常,加入自己的理解的error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。
    12.【推荐】定义时区分unchecked / checked 异常,避免直接使用RuntimeException抛出,更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常。推荐业界已定义过的自定义异常,如:DaoException /ServiceException等。
    13.【参考】避免出现重复的代码(Don’t RepeatYourself),即DRY原则。
    说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是共用模块。
    正例:一个类中有多个public方法,都需要进行数行相同的参数校验操作,这个时候请抽取:
    private boolean checkParam(DTO dto){…}

日志规约

  1. 【强制】应用中不可直接使用日志系统中的API,而应依赖使用日志工具或者jar包中的API,有利于维护和各个类的日志处理方式统一。
  2. 【强制】完整的日志信息,即:属于什么应用,什么类型,什么目的,也有利于归类定位查找。
  3. 【强制】避免重复打印日志,浪费磁盘空间以及系统资源。
  4. 【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么往上抛。
    正例:logger.error(各类参数或者对象 toString + “_” + e.getMessage(), e);
  5. 【推荐】输出的 POJO类必须重写 toString方法,否则只输出此对象的 hashCode值(地址值),没啥参考意义。
  6. 【推荐】可以使用 warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。注意日志输出的级别,error级别只记录系统逻辑出错、异常、或者重要的错误信息。如非必要,请不要在此场景打出 error级别,避免频繁报警。
  7. 【推荐】谨慎地记录日志。生产环境禁止输出 debug日志;有选择地输出 info日志;如果使用 warn来记录刚上线时的业务行为信息,一定要注意日志输出量的问题。
    说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。纪录日志时请
    思考:这些日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?
    8.【参考】如果日志用英文描述不清楚,推荐使用中文注释。对于中文 UTF-8的日志,在 secureCRT中,setencoding=utf-8;如果中文字符还乱码,请设置:全局>默认的会话设置>外观>字体>选择字符集 gb2312;如果还不行,执行命令:set termencoding=gbk,并且直接使用中文来进行检索。

说明:本规范使用阿里巴巴代码规范插件(Alibaba Java Coding Guidelines)进行检测,可参考:https://www.cnblogs.com/ysgcs/p/7675977.html,该规范属Java格式规范,开发时可直接使用AS格式化即可。
欢迎交流:604254827

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值