Android 开发规范

1.AS规范

  1. 尽可能使用最新的稳定的IDE进行开发;
  2. 编码格式统一为 UTF-8;
  3. 删除多余的 import,减小警告出现,可利用 AS 的 Optimize Imports(Settings -> Keymap -> Optimize Imports)快捷键;

2.命名规范

代码中的命名严禁使用拼音与英文混合的方式,更不容许直接使用中文的方式。java

2.1 包

2.1.1 包名

  1. 包名必须是所有小写,连续的单词只是简单地链接起来,不使用下划线,采用反域名命名规则。
  2. 一级包名为顶级域名,一般为 comedu
  3. 二级包名为公司名,如 denglin
  4. 三级包名为应用名,如 rubbish

2.1.2 包名划分

  1. 推荐采用PBF(按照功能分包Package By Feature)不建议使用PBL(按层分包 Package By Layer)
  2. 按照功能分包具体能够这样作:
com
└── domain
    └── app
        ├── App.java 定义 Application 类
        ├── Config.java 定义配置数据(常量)
        ├── Activity  
        │   ├── HomeActivity 
        │   ├── LoginActivity 
        │   ├── AboutActivity 
        ├── base 基础组件
        ├── custom_view 自定义视图
        ├── data 数据处理
        │   ├── DataManager.java 数据管理器
        |   ├── Aes.java Aes数据加密解密
        │   ├── local 来源于本地的数据,好比 SP,Database,File
        │   ├── model 定义 model(数据结构以及 getter/setter、compareTo、equals 等等,不含复杂操做)
        │   └── remote 来源于远端的数据
        ├── feature 功能
        │   ├── feature0 功能 0(搜索垃圾分类)
        │   │   ├── feature0Fragment.java
        │   │   ├── xxAdapter.java
        │   │   └── ... 其余 class
        |   ├── feature1 功能 1(获取垃圾搜索热点)
        │   │   ├── feature1Fragment.java
        │   │   ├── xxAdapter.java
        │   │   └── ... 其余 class
        |   ├── feature2 功能 2(app启动时同步最新垃圾分类数据)
        │   │   ├── feature1Fragment.java
        │   │   ├── xxAdapter.java
        │   │   └── ... 其余 class
        │   └──....其余功能
        ├── injection 依赖注入
        ├── util 工具类(例如网络请求,数据上传)
        └── widget 小部件
复制代码

2.2 类

2.2.1 类名

  • 使用驼峰命名 例如: LoginActivity
  • 尽可能不使用缩写

常见类命名格式数据库

描述 例如
Activity Activity 为后缀标识 主页面类 HomeActivity
Adapter Adapter 为后缀标识 新闻详情适配器 NewsDetailAdapter
解析类 Parser 为后缀标识 首页解析类 HomePosterParser
工具方法类 UtilsManager 为后缀标识 打印工具类:PrinterUtils
数据库类 DBHelper 后缀标识 新闻数据库:NewsDBHelper
Service Service 为后缀标识 时间服务 TimeService
BroadcastReceiver Receiver 为后缀标识 推送接收 JPushReceiver
ContentProvider 以 Provider 为后缀标识 ShareProvider
自定义的共享基础类 Base 开头 BaseActivity, BaseFragment

2.2.2 接口

  • 使用驼峰命名 多以able或者ible结尾 例如:interface Runnable
  • 若是项目采用MVP设计,全部 ModleViewPresenter 的接口都是以 I 为前缀,不加后缀,其余的接口采用上述命名规则。

2.3 方法名

  • 方法名以 lowerCamelCase 风格编写。
  • 方法名一般是动词或动词短语。

常见方法命名数组

方法 说明
initXX() 初始化相关方法,例:初始化布局 initView()
isXX() checkXX() 方法返回boolean类型
getXXX() 返回某个值的方法
setXXX() 设置某个属性值
handleXXX() processXXX() 对数据进行处理的方法
displayXXX() showXX() 显示提示框或者消息提示
updateXX() 更新数据
saveXXX() 保存数据
clearXXX() 清除数据
removeXXX() 移除数据或者视图等,如:removeView()
drawXXX() 绘制数据或者效果相关等

2.4 常量名

  • 常量名命名所有字母大写, 用下划线分割单词。 例如: CONSTANT_CAS
  • 常量名都是一个静态 final 字段,但不是全部静态 final 字段都是常量。
static final int VERSION = 1;
static final String VERSION_NAME "hello world";
复制代码

2.5 很是量字段名

很是量字段名以 lowerCamelCase 风格的基础上改造为以下风格: 基本结构为 scopeVariableNameTypebash

2.5.1 scope (范围)

  • 非公有,非静态字段命名为 m 开头。
  • 静态字段命名为 s 开头。
  • 其余字段以小写字母开头。

例如:网络

public class MyClass {
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}
复制代码

使用 1 个字符前缀来表示做用范围,1 个字符的前缀必须小写,前缀后面是由表意性强的一个单词或多个单词组成的名字,并且每一个单词的首写字母大写,其它字母小写,这样保证了对变量名可以进行正确的断句。数据结构

2.5.2 控件类型

为了不控件和普通成员变量混淆以及更好地表达意思,全部用来表达控件的成员变量统一加上控件缩写做为前缀app

UI控件缩写表dom

名称 缩写
Button btn
CheckBox cb
EditText et
FrameLayout fl
GridView gv
ImageButton ib
ImageView iv
LinearLayout ll
ListView lv
ProgressBar pb
RadioButtion rb
RecyclerView rv
RelativeLayout rl
ScrollView sv
SeekBar sb
Spinner spn
TextView tv
ToggleButton tb
VideoView vv
WebView wv

2.6 变量名

变量名中可能会出现量词,咱们须要建立统一的量词,他们更容易理解,也更容易搜索。 例如: mFirstBookmPreBookcurBookide

量词列表 量词后缀说明
First 一组变量中的第一个
Last 一组变量中的最后一个
Next 一组变量中的下一个
Pre 一组变量中的上一个
Cur 一组变量中的当前变量

3. 代码规范

3.1使用标准大括号样式

左大括号不单独占一行,与其前面的代码位于同一行:函数

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}
复制代码

须要在条件语句周围添加大括号。例外状况整个条件语句适合放在同一行,那么能够将其所有放在一行上。例如,咱们接受一下样式:

if (condition) {
    body();
}
复制代码

也能够接受一下样式:

if (condition) body();
复制代码

但不接受一下样式:

if (condition)
    body(); 
复制代码

3.2 类成员的顺序

推荐使用以下的排序顺序:

  1. 常量
  2. 字段
  3. 构造函数
  4. 重写函数和回调
  5. 公有函数
  6. 私有函数
  7. 内部类或接口 例如:
public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private String mTitle;
    private TextView mTextViewTitle;

    @Override
    public void onCreate() {
        ...
    }

    public void setTitle(String title) {
    	mTitle = title;
    }

    private void setUpView() {
        ...
    }

    static class AnInnerClass {

    }
}
复制代码

若是类继承于Android组件例如:Activity,那么把重写函数按照他们的生命周期进行排序是一个很是好的习惯。例如:

public class MainActivity extends Activity {
    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}

    @Override
    public void onResume() {}

    @Override
    public void onPause() {}

    @Override
    public void onDestroy() {}
}
复制代码

3.3 函数参数的排序

在Android开发过程当中, Context 在函数参数中是再常见不过的了,咱们最好把 Context 做为函数的第一个参数。

相反,咱们回调接口应该做为其最后一个参数。

例如:

// Context always goes first
public User loadUser(Context context, int userId);

// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);
复制代码

3.4 字符串常量的命名和值

Android SDK中的不少类都用到了键值对函数,好比 SharedPreferencesBundleIntent ,因此,即使是一个小应用,咱们最终也不得不编写大量的字符串常量。

当咱们用到这些类时,必须将他们的将定义为 static final 字段,而且遵循如下指示做为前缀。

字段名前缀
SharedPreferences PREF_
Bundle BUNDLE_
Fragment Arguments ARGUMENT_
Intent Extra EXTRA_
Intent Action ACTION_

说明:虽然 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.5 Activities 和 Fragments 的传参

当 Activity 或 Fragment 传递数据经过 Intent 或 Bundle 时,不一样值的键须遵循上一条所说起到的。

当 Activity 或 Fragment 启动须要传递参数时,那么它须要提供一个 public static 的函数来帮助启动或建立它。

这方面,AS 已帮你写好了相关的 Live Templates,启动相关 Activity 的只须要在其内部输入 starter 便可生成它的启动器,以下所示:

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;
}
复制代码

4. 行长限制

4.1 换行策略

  1. 除赋值操做以外,咱们把换行符放在操做符以前,例如:
int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
        + theFinalOne;
复制代码
  1. 赋值操做符的换行咱们放在其后,例如:
int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
复制代码

4.2 函数链的换行

当同一行中调用多个函数时,对每一个函数的调用都应该在行的一行中,咱们把换行符插入在 . 以前。

例如:

Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);
复制代码

应该使用以下规则:

Picasso.with(context)
        .load("https://blankj.com/images/avatar.jpg")
        .into(ivAvatar);
复制代码

4.3 多参数的换行

当一个方法有不少参数或者参数很长的时候,咱们应该在每一个 , 后面进行换行。 好比:

loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);
复制代码

应该使用以下规则:

loadPicture(context,
        "https://blankj.com/images/avatar.jpg",
        ivAvatar,
        "Avatar of the user",
        clickListener);
复制代码

4.4 RxJava 链式换行

RxJava 的每一个操做符都须要换新行,而且把换行符插入在 . 以前。

例如:

public Observable<Location> syncLocations() {
    return mDatabaseHelper.getAllLocations()
            .concatMap(new Func1<Location, Observable<? extends Location>>() {
                @Override
                 public Observable<? extends Location> call(Location location) {
                     return mRetrofitService.getLocation(location.id);
                 }
            })
            .retry(new Func2<Integer, Throwable, Boolean>() {
                 @Override
                 public Boolean call(Integer numRetries, Throwable throwable) {
                     return throwable instanceof RetrofitError;
                 }
            });
}
复制代码

5.资源文件规范

6.注释规范

6.1类注释

每一个类完成后应该有做者姓名和联系方式的注解,对本身的代码负责。 例如:

/**
 * author : Blankj
 * time   : 2019/07/13
 * desc   : xxxx 描述
 * version: 1.0
 */
public class WelcomeActivity {
    ...
}

复制代码

具体能够在AS在那个本身配置,进入 Settings -> Editor -> File and Code Templates -> Includes -> File Header,输入

/**
 * author : ${USER}
 * time   : ${YEAR}/${MONTH}/${DAY}
 * desc   : 
 * version: 1.0
 */
复制代码

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

6.2方法注释

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

/**
 * bitmap 转 byteArr
 *
 * @param bitmap bitmap 对象
 * @param format 格式
 * @return 字节数组
 */
public static byte[] bitmap2Bytes(Bitmap bitmap, CompressFormat format) {
    if (bitmap == null) return null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(format, 100, baos);
    return baos.toByteArray();
}
复制代码

6.3块注释

块注释与其周围的代码在同一缩进级别。它们能够是 /* ... */ 风格,也能够是 // ... 风格(// 后最好带一个空格)。对于多行的 /* ... */ 注释,后续行必须从 * 开始, 而且与前一行的 * 对齐。如下示例注释都是 OK 的。

/*
 * This is
 * okay.
 */

// And so
// is this.

/* Or you can
* even do this. */
复制代码

6.4其余注释

AS 已帮你集成了一些注释模板,咱们只须要直接使用便可,在代码中输入 todo、fixme 等这些注释模板,回车后便会出现以下注释。

// TODO: 17/3/14 须要实现,但目前还未实现的功能的说明
// FIXME: 17/3/14 须要修正,甚至代码是错误的,不能工做,须要修复的说明
复制代码
相关文章
相关标签/搜索