Android代码规范

前言

一个良好的代码规范,能够在项目当中发挥举足轻重的作用;它不仅能使我们的开发更加高效,而且还会减少BUG产生的几率,增强代码可维护性及稳定性。

JAVA代码规范

强制性规范:

  1. 代码中的命名均不能以下划线美元符号开始,也不能以下划线或美元符号结束
  2. 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
  3. 名使用UpperCamelCase 风格,必须遵从驼峰形式。
  4. 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
  5. 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长例如:MAX_STOCK_COUNT
  6. 抽象类命名使用 AbstractBase 开头;
  7. 异常类命名使用 Exception 结尾;
  8. 测试类 命名以它要测试的类的名称开始。
  9. 杜绝不规范的英文缩写:AbstractClass 缩写成AbsClass;condition缩写成condi;此类随意缩写严重降低了代码的可阅读性。
  10. 如果使用到了设计模式,建议在类名中体现出具体的模式:
   public class ComponentFactory
   public class BufferStrategy
   public class ScrollerProxy

  1. 关于Service或Dao层的命名

插入:insert(推荐)或save
删除:delete
修改:update(推荐)或modify
查询单个对象:get
查询多个对象:list

  1. 实体类必须重载toString()方法,这样可以通过调用对象的toString()来排查问题。
  2. Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

正例: “test”.equals(object);
反例: object.equals(“test”);

  1. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

推荐规范:

  1. 集合初始化时,尽量指定集合初始值大小;

ArrayList尽量使用ArrayList(int initialCapacity) 初始化 。

  1. 使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历

说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效 率更高。如果是 JDK8,使用 Map.foreach 方法。

  1. 高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:
集合类KeyValueSuper说明
Hashtable不允许为null不允许为nullDictionary线程安全
ConcurrentHashMap不允许为null不允许为nullAbstractMap分段锁技术
TreeMap不允许为null允许为nullAbstractMap线程不安全
HashMap允许为null允许为nullAbstractMap线程不安全
  1. 利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains 方法进行遍历、对比、去重操作。
  2. 通过双重检查锁(double-checked locking)(在并发场景)实现延迟初始化的优 化问题隐患(可参考 The “Double-Checked Locking is Broken” Declaration),推荐问题 解决方案中较为简单一种(适用于 JDK5 及以上版本),将目标属性声明为 volatile 型。
*反例*:
class Foo {
    private Helper helper = null;

    public Helper getHelper() {
     if (helper == null) 
            synchronized(this) { 
                if (helper == null)
                    helper = new Helper(); 
            } 
            return helper; 
    } 
// other functions and members... 
} 

Android代码规范

代码:

  1. Activity 命名一律使用 模块名+Activity 的方式。例如,LoginActivity、SignupActivity
  2. Fragment 命名一律使用 模块名+Fragment 的方式;
  3. 自定义View:Custom(建议)+功能名+View/ViewGroup(具体的组件名称)。例如:CustomImageScrollerCustomRatingBar
  4. Widget 小组件:ScanWidget、WeatherWidget
  5. Dialog对话框:功能名+Dialog。例如:LoginDialog、ProgressDialog
  6. 尽量在每一个Activity或类中加入TAG,方便我们查看Activity的信息,这里Android Studio提供了快捷方式logt方式即可快速生成当前类的常量。
  7. 对于使用Intent传递数据,声明一些Key的时候:

EXTRA_KEY_+具体Key名称,例如我们现在有一个人的名字和年龄要传那么首先定义:

public static final String EXTRA_KEY_PERSON_NAME="EXTRA_KEY_PERSON_NAME"
public static final String EXTRA_KEY_PERSON_NAME="EXTRA_KEY_PERSON_AGE"

然后在具体的页面 new Intent(),依次传递进去值,这样写其实没什么问题;但是试想一下,如果你要调用的Activity是类似于一个工具性质或通用的Activity(图片选择器、登录、注册等等),这时候你要传递的key又很多,如果业务复杂的话,你应该会被这样冗余且不易阅读的代码直接搞崩溃掉。

所以最好的办法就是在你要调用Activity提供一个静态工厂方法,要知道静态工厂方法所带来的好处太多了,由于Activity是不允许通过new的方式来初始化的,所以静态工厂方法的好处在此就不那么明显,但是已经足够我们优化我们的代码了。举个例子,我们有一个笔记 NoteActivity,用于创建笔记和修改笔记,

//笔记Id
private static final String EXTRA_KEY_NOTE_ID ="EXTRA_KEY_NOTE_ID" ;
//笔记内容
private static final String EXTRA_KEY_NOTE_CONTENT ="EXTRA_KEY_NOTE_CONTENT" ;
//笔记模式
private static final String EXTRA_KEY_NOTE_MODE ="EXTRA_KEY_NOTE_MODE" ;

//用于创建笔记
public static void startForCreate(Context context, int noteId) {
    start(context, noteId, null, MODE_CREATE);
}

//用于编辑笔记
public static void startForEdit(Context context, int noteId, String content) {
    start(context, noteId, content, MODE_UPDATE);
}

public static void start(Context context, int noteId, String content, int mode) {
    Intent starter = new Intent(context, TableShareListSettingActivity.class);
    starter.putExtra(EXTRA_KEY_NOTE_ID,noteId);
    starter.putExtra(EXTRA_KEY_NOTE_CONTENT,content);
    starter.putExtra(EXTRA_KEY_NOTE_CONTENT,mode);
    context.startActivity(starter);
}

通过以上方法,我们能够很好的解耦复杂的Activity之间的调用,再加上静态方法工厂方法名,代码可阅读行大大提高,最终我们看到的调用NoteActivity将会是很简洁的一段代码:

NoteActivity.startForCreate(this,noteId);
NoteActivity.startForEdit(this,noteId,content);

此外,Android Studio工具中其实已经在Live Template中提供了这样的代码:CMD+J( For MAC OS),简单的输入starter就可以快速地在当前的Activity中添加一个Intent的静态操作方法,这其实也说明了Android官方团队也鼓励我们这么做。
如下图所示:

《Android代码规范》

一下子省了好多代码,简直太赞了有木有!

  1. 增加类注释,使用Android Studio的 File And Code Template:

《Android代码规范》
《Android代码规范》

  1. 所有的常量加上注释,且功能相同的排放在一起,不同的进行换行;
  2. Activity中变量采用m开头+类名。例如,mTable、mPerson;
  3. Activity中的控件:m+模块名+控件类型名称。例如,mLoginEditText,mLoginTextView;

资源Res

1.按照资源的类型,分为以下几种

控件Id命名:控件缩写 _模块(module) _功能名(function)

控件类型ID命名规则
TextViewtv_module_function
EditTextet_module_function
ImageViewiv_module_function
Buttonbtn_module_function
ListViewlv_module_function
GridViewgv_module_function
CheckBoxcheck_module_function
RadioButtonradio_module_function
LinearLayoutll_module_function
RelativeLayoutrl_module_function
FrameLayoutfl_module_function
GridLayoutgl_module_function
······

Color资源命名

Resources Type命名规则
color组件名+具体作用名。例 R.color.button_text

String资源命名

Resources Type命名规则
string具体功能。 例 R.string.hello

Drawable资源命名

Resources Type命名规则
launcher iconic_launcher。例R.drawable.ic_launcher
normal iconic_具体模块_功能。例R.drawable.ic_audio_pause
Toolbar iconic_ab_功能名。例如ic_ab_search
selectorselector_模块_功能名。例如 selector_login_button
shapeshape_模块功能名状态。例如 R.drawable.shape_login_button_pressed ,R.drawable.shape_login_button_normal

Layout资源命名

类型命名规则
activityactivity_模块名。例如 R.layout.activity_login
fragmentfragment_模块名。例如 R.layout.fragment_login_layout_header
includelayout_模块名_功能名。例如 @layout/layout_login_bottom
adapteradapter_item_模块名_功能名。例如 R.layout.adapter_item_simple_text
dialogdialog_模块_功能名。例如 R.layout.dialog_time_picker
list headerheader_模块_功能。例如 R.layout.header_main_top_ad
list footerfooter_模块_功能。例如 R.layout.footer_main_bottom_action
widgetwidget_模块_功能。例如 R.layout.widget_app_clock
······

Menu资源命名

Resources Type命名规则
menumenu_模块名。例如 menu_login

Values资源命名

Resources Type命名规则
color模块名_color。例如 material_design_color
dimens模块名_dimens。例如 material_design_dimens
style模块名_style。例如 material_design_style
themes模块名_themes。例如 material_design_themes

附录

UI控件缩写表

控件缩写例子
LinearLayoutllllFriend或者mFriendLL
RelativeLayoutrlrlMessage或mMessageRL
FrameLayoutflflCart或mCartFL
TableLayouttltlTab或mTabTL
ButtonbtnbtnHome或mHomeBtn
ImageButtonibtnbtnPlay或mPlayIBtn
TextViewtvtvName或mNameTV
EditTextetetName或mNameET
ListViewlvlvCart或mCartLV
ImageViewivivHead或mHeadIV
GridViewgvgvPhoto或mPhotoGV

常见的英文单词缩写

名称缩写
iconic (主要用在app的图标)
colorcl(主要用于颜色值)
dividerdi(主要用于分隔线,不仅包括Listview中的divider,还包括普通布局中的线)
selectorsl(主要用于某一view多种状态,不仅包括Listview中的selector,还包括按钮的selector)
averageavg
backgroundbg(主要用于布局和子布局的背景)
bufferbuf
controlctrl
deletedel
documentdoc
errorerr
escapeesc
incrementinc
infomationinfo
initialinit
imageimg
InternationalizationI18N
lengthlen
librarylib
messagemsg
passwordpwd
positionpos
serversrv
stringstr
temptmp
windowwnd(win)

参考资料

阿里巴巴Java开发手册

Google Java Style Guide

一些插件

ADB Idea
adb常用命令,ctrl+shift+a输入adb可调用

Android Methods Count
引用库方法数统计

Exynap
快速使用代码模板,ctrl+shift+d调用

ADB WIFI
无需root就能wifi调试

CodeGlance
最大的用途:可用于快速定位代码

Lifecycle-Sorter
可以根据Activity或者fragment的生命周期对其生命周期方法位置进行先后排序, 快捷键Ctrl + alt + K

folding-plugin
可以给资源文件分组,并且不移动文件,也不会创建文件夹:Android File Grouping Plugin

strings-xml-tools
管理Android工程中字符串国际化的插件

.ignore:
.gitignore配置插件。

AndroidLocalizationer
可用于将项目中的 string 资源自动翻译为其他语言的 Android Studio/IntelliJ IDEA 插件

Alibaba Coding Guidelines

    原文作者:三也视界
    原文地址: https://www.jianshu.com/p/4ad8f6eb527c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞