抱歉,你查看的文章不存在

Android开发基础规范(一)

【小提醒】阅读本文约耗时3分钟左右。

前言:Android中一些开发规范,避免给自己和别人少留坑。

一、工程相关

  • 1.1 工程结构 当进行提交代码的工作时,工程应该保持如下的目录结构:

当你修改或者增加新功能的时候,工程结构依然应该保持如上的样子。 使用如上的工程结构可以让我们的应用代码从相关的测试代码中分离出来。 CommonTest目录使得我们的功能测试和单元测试可以共享部分代码,比如mock model creation and dagger test configuration classes.

  • 1.2 文件命名
    • 1.2.1 类文件 任何定义的类都应该使用驼峰命名格式,比如:

任何继承自android组件的类都应该使用组件名称来结尾,比如:

  • 使用驼峰格式命名易于阅读。
  • 用android组件名称结尾的继承类能够清楚的标识出类的用途,比如,如果要去查找修改RegistrationDialog时,那么这个命名使得定位这个类文件非常方便。
    • 当命名资源文件时,应该只使用小写字母和下划线替代空格,例如: activity_main, fragment_user, item_post 在你查找布局文件时,这样命名同样使得定位文件很方便。
    • 在使用android studio中,布局的package中的文件是按字母顺序排列的,这样意味activity,fragment和其他的layout是按组分类放置的,所以你知道从哪里去开始找一个文件了。
    • 不仅如此,用组件名称开头的布局文件可以很清晰的表示这个布局文件是被那类组件使用。
    • 1.2.2 资源文件
  • 1.2.2.1 Drawable 文件
    • Drawable资源文件应该使用“ic_”前缀后跟上尺寸以及资源的颜色信息 For example, white accept icon sized at 24dp would be named: 比如,白色的24dp大小的用于接受动作的图标应该命名如下: ic_accept_24dp_white 黑色用于取消动作的48dp大小的图标命名: ic_cancel_48dp_black 我们使用这样的命名约定方便使用命名来组织drawable资源文件
    • 如果命名中没有颜色和尺寸信息,那么开发者还需要打开drawable文件去查看这些信息。所以这样可以节约我们时间.其他的drawable文件应该使用对应的前缀,如下:

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

Type

Prefix

Example

Selector

selector_

selector_button_cancel

Background

bg_

bg_rounded_button

Circle

circle_

circle_white

Progress

progress_

progress_circle_purple

Divider

divider_

divider_grey

在Android Studio中这个命名约定依然可以帮助我们将相似的组织到一起 并清晰的标识出这一文件用作什么 比如, 命令一个资源为“button_cancel”不能标识任何信息 这是一个selector资源呢还是一个圆角按钮背景呢? 正确的命名可以去除所有的引起的模糊不清. 在创建selector不同状态资源时,也应该使用对应的命名下标:

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

State

Suffix

Example

Normal

_normal

btn_accept_normal

Pressed

_pressed

btn_accept_pressed

Focused

_focused

btn_accept_focused

Disabled

_disabled

btn_accept_disabled

Selected

_selected

btn_accept_selected

使用如上清晰的下标绝对明显的标识出了selector状态资源的作用。 为有颜色和其他标识的资源文件增加下标,使得开发者在打开selector文件时就可以知道不同的selector资源的状态是什么

1.2.2.2 Layout 文件 在命名布局文件时,应该用android组件的名称作为文件名的前缀,比如:

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

Component

Class Name

Layout Name

Activity

MainActivity

activity_main

Fragment

MainFragment

fragment_main

Dialog

RateDialog

dialog_rate

Widget

UserProfileView

view_user_profile

AdapterView

Item

N/A item_follower

注意:如果要创建的布局文件是有多个不同组件使用的,那么应该使用”layout_”前缀 这样不仅在层级目录中可以很方便的找到文件, 这样也可以帮助我们定义相应的这个layout布局文件归属的类。

1.2.2.3 Menu Files 菜单文件不需要使用“menu_”前缀。 在资源目录下已经有菜单包了,所以这是不必要的。

1.2.2.4 Values Files 所有的资源文件名必须是复数的,比如: attrs.xml, strings.xml, styles.xml, colors.xml, dimens.xml

二、代码相关

  • 2.1 Java语句规则
    • 2.1.1 绝不要忽略exceptions 正确的方式是避免没有处理的异常,如下:
//create by 逆流的鱼yuiop on 2016/9/21//blog地址:http://blog.csdn.net/hejjunlinpublic void setUserId(String id) {    try {
        mUserId = Integer.parseInt(id);
    } catch (NumberFormatException e) { }
}

如果这里出现问题,这里不会打印出任何信息,而且也很难debug,只能让人迷惑。 当catch一个异常时,我们总是需要输出error日志到控制台,用于调试,如果必要的话,需要警告用户这个异常。比如:

这里我们有如下的方式处理出错:

  • 显示一个信息给用户,提示他们这里出错了
  • 设置了一个可能的默认值
  • 抛出了一个合适的异常

2.1.2 不要catch最大的异常(Exception):

为什么不这样做呢?

在大部分情况下,catch这个大的Exception或者Throwable都是不合适的。(特别是Throwable因为它包含Error的异常。) 这样意味着你没有期望到的最终要捕获的异常(包括RuntimeExceptions像CLassCastException)都被捕获并在应用层进行error处理,这样是很危险的。 如果有人在你调用的代码里添加了一个新的类型的异常,编译器不会帮你认识到你需要处理这个不同的错误类型。这是你代码里很难发现的错误处理方式。 大多数情况下,你不应该用相同的处理方式来处理不同的exception. 如下,catch期望的异常并正确的处理:

2.1.3 组织 exceptions

在异常运行相同的代码的地方,他们应该增加可读性和避免代码复制。比如,你可能会像如下这样处理异常:

你可以这样做:

2.1.4 Using try-catch over throw exception

在exception出现的地方使用try-catch块增加代码可读性 在代码中error发生的地方就处理,这样不管是debug还是更改error处理都很容易。

2.1.5 不要使用垃圾回收器

  • 不能保证什么时候垃圾回收器会被调用,也不能保证垃圾回收器将在什么时候调用.
  • 大部分情况下,在有规范的异常处理的情况下,你可以做你需要做的。 如果你实在需要,定义一个close()方法(或者类似的)并在方法调用时,提醒记得close
  • 以InputStreamfor作为example.
  • 在这种情况下是可以的,但是不需要从垃圾回收器中输出少量日志信息,也不需要输出大量日志.

2.1.6 完全限制方式导包

  • 导包时,使用全包格式,例如:
  • 不要这样导包: import android.support.v7.widget.*;
  • 而是要这样: import android.support.v7.widget.RecyclerView;

2.1.7 去掉无用的包引入

  • 通常从一个类中移除代码意味着一些之前引入的包也已经不需要。 这种情况下,不需要导入的包应该和代码一起移除掉。

2.2 Java样式规则

2.2.1 属性定义和命名

  • 所有的字段都应该在文件顶部定义,遵循如下规则: private, non-static 字段应该用“m”做前缀,像如下的例子是正确的: mUserSignedIn, mUserNameText, mAcceptButton
  • 所有其他的字段都用小写字母开头: int numOfChildren; String username; static final 字段(静态的)全部大写 private static final int PAGE_COUNT = 0;
  • 类属性命名没有显示任何信息的不应该适用,比如: int e; //number of elements in the list
  • 为什么一开始不给属性一个有意义的名字,而给一段comment呢? int numberOfElements;

2.2.1.2 View属性名称

当为一个界面控件定义一个类属性时,view应该作为这个属性的后缀,比如:

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

View

Name

TextView

mUsernameView

Button

mAcceptLoginView

ImageView

mProfileAvatarView

RelativeLayout

mProfileLayout

  • 我们这样命名view以便我们可以知道这个类属性和什么资源关联.
  • 比如, 给定像这样的类属性命名: mUsernameView,mUserAvatarView或者mUserProfieLayout
  • 这些命名很清晰的表明其对应的资源
  • 以前,控件属性的命名通常用控件类型来结尾(比如acceptLoginButton),但是控件经常改变而且很容易忘记到java类中去更新变量的名称.

2.2.2 命名属性时不要包含容器类型

  • 根据上一条的规则,同样我们应该避免在创建集合变量时使用集合类型来命名.比如,假如我们有一个使用arrayList包含userIds的列表:
  • 使用: List userIds = new ArrayList<>();
  • 不要使用: List userIdList = new ArrayList<>();
  • 当集合容器改变类型后,如上的命名可能会经常忘记去更改 就像控件命名那样,所以没有必要包含容器类型.
  • 容器变量正确的命名应该包含足够的变量信息.

2.2.3 避免相似的命名

  • 使用相似的名称来命名变量,方法或者类时,会使其他开发者在阅读您的代码时迷惑.比如: hasUserSelectedSingleProfilePreviously hasUserSelectedSignedProfilePreviously
  • 很难第一眼就可以区分出上面两个变量是干什么的.使用更清晰的方式命名变量可以使得其他开发者更容易通过变量名理解您的代码.

2.2.4 数字连续命名

  • 当Android Studio自动为我们产生代码,这样很容易给我们留下问题,特别是当它产生糟糕的命名时.比如,这样就很不好: public void doSomething(String s1, String s2, String s3)
  • 不阅读代码的话很难理解如上这个方法中的参数是做什么的. public void doSomething(String userName, String userEmail, String userId) 这样就容易理解得多了.我们可以根据这个更容易理解的方法参数去阅读代码了

2.2.5 易读的命名

在对属性,方法和类命名时,应该遵循如下规则:

  • 可读:有效的命名意味着我们可以立刻通过名称就理解,减少译解名称的认知负担.
  • 可拼写:在您尝试对命名很糟糕的名称发音时,可拼写的命名可以避免笨拙的对话.
  • 可搜索:没有比在一个类中搜索一个方法或者变量时发现名称拼写错误或者命名很糟糕.当我们想找到一个关于查找用户的方法时,直接搜索字符串 ‘search’ 就应该保护这个方法的结果.
  • 不要使用匈牙利标记法:匈牙利标记法和上面三条冲突,不要使用.

2.2.6 将带缩写词(那些将所有字母都大写的词)作为单词使用

在任意类名,变量名中使用的缩写词都应该作为单词使用.比如:

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

Do

Don’t

setUserId

setUserID

String uri

String URI

int id

int ID

parseHtml

parseHTML

generateXmlFile

generateXMLFile

2.2.7 避免对齐变量声明

任何变量的声明都不应该使用特殊的对齐格式,比如: 这样就很好:

不要这样做:

这样产生了很多空白,让代码难于阅读.

2.2.8 使用空格符进行缩进

  • 对于语句块,应该使用4个空格符缩进: if (userSignedIn) { count = 1; } 在自动换行时,应该使用8个空格符缩进:

2.2.9 If-Statement语句

  • 2.2.9.1 使用标准的大括号样式 大括号应该与其前面的代码放置在同一行。例如,避免下面这样的代码出现:

取而代之应该这样:

这不仅是没有必要增加额外的一行,而它还会让读取代码变得更加容易

  • 2.2.9.2 Inline if-clauses 内联if从句
    • 有时使用单行if语句是有意义的。例如: if (user == null) return false;
    • 然而,它仅适用于简单的操作。像下面这样的代码会更适合使用大括号: if (user == null) throw new IllegalArgumentExeption(“Oops, user object is required.”);
  • 2.2.9.3 Nested if-conditions 嵌套的if条件语句 在可能的情况下,if语句的条件应该合并,避免过于复杂的嵌套,例如: 推荐:

避免像下面这样:

这会使得代码更加容易阅读,并且从嵌套语句中移除不必要的行数。

  • 2.2.9.4 Ternary Operators 双目运算符
    • 在适当的情况下,双目运算符能够用来简化操作。 例如,下面的代码很容易阅读:

注意:在有些情况下双目运算符不应该使用。如果if语句的逻辑过于复杂或者包含了大量的字符,这时应该使用标准的大括号样式。

2.2.10 Annotations 注解

2.2.10.1 Annotation practices 注解用法 从《Android code style guidelines》中获悉:

  • @Override: @Override注解必须使用在当重写方法时候的声明或者实现父类时。例如,如果你使用 @inheritdocs文档标签,并且派生一个类(而不是一个接口),对于重写的父类方法你也必须使用 @Override注解。
  • @SuppressWarnings: @SuppressWarnings注解应该仅使用在不可能清除警告的情况下,如果一个警告通过了“不可能消除”测试, @SuppressWarnings注解必须使用,以便在代码中确保所有的警告反映实际问题。 有关注解指引的更多信息可以在这里找到。
  • 注解应该使用在可能需要的地方。例如,可使用@Nullable注解已免出现属性为空的情况。例如:

2.2.10.2 Annotation style 注解样式 应用在方法或者类的注解应该总是在声明中定义,并且每一项只能一行:

当在属性上使用注解时,应确保注解与属性在同一行,例如:

它会使得声明阅读起来更加容易。例如,在声明 ‘@Inject SomeComponent mSomeName’ 可读为’inject this component with this name’(利用这个名字注入组件)。

2.2.11 Limit variable scope 限制变量的作用域

  • 局部变量的作用域应保持在最低限度(《Effective Java》第29条建议)。这样做的话,将会提高代码的可读性和可维护性,同时减少出错的可能性。
  • 所有要使用的每一个变量都应该在语句块中声明。 局部变量应当在其第一次使用处声明。几乎每一个局部变量的声明都应该包含一个初始化。如果你还没有足够的信息来合理地初始化变量,你应该推迟声明直到你需要的时候。

2.2.12 Unused elements 无用的元素

  • 所有无用的属性、导入、方法和类应该从代码中移除,除非有特殊的用途保留这些。

2.2.13 Order Import Statements 导入声明 因为我们使用的是Android Studio,因此导入都是自动的按序导入。然而,在一些情况下并非如此,因此应按照下面的顺序导入:

  • 1.Android imports
  • 2.Imports from third parties
  • 3.java and javax imports
  • 4.Imports from the current Project

注意: - 1.每个组的导入应按照字母的顺序排列,大写字母排在小写字母之前(Z排在a之前) - 2.在各个组之间应该空一行(android, com, JUnit, net, org, java, javax) 2.2.14 Logging 日志 日志通常在开发过程中用于记录有用的错误消息或者其他可能有用的信息。

//create by 逆流的鱼yuiop on 2016/9/21 //blog地址:http://blog.csdn.net/hejjunlin

Log

Reason

Log.v(String tag, String message)

verbose (详细)

Log.d(String tag, String message)

debug(调试)

Log.i(String tag, String message)

information(普通info)

Log.w(String tag, String message)

warning(警告)

Log.e(String tag, String message)

error (错误)

我们做日志记录时可以设置一个标示,这个TAG是一个静态的final属性,放置在类的顶部,例如: private static final String TAG = MyActivity.class.getName(); 所有的调试日志不应该出现在发布的版本中,另一方面,信息、警告和错误日志只有在需要的时候保持开启。

原文发布于微信公众号 - 何俊林(DriodDeveloper)

原文发表时间:2016-09-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

编辑于

码农突围

0 篇文章93 人订阅

相关文章

来自专栏落花落雨不落叶

杭电2016 数据的交换输出

373120
来自专栏Golang语言社区

GO语言标准库概览

在Go语言五周系列教程的最后一部分中,我们将带领大家一起来浏览一下Go语言丰富的标准库。 Go标准库包含了大量包,提供了丰富广泛的功能特性。这里提供了概览仅仅是...

76260
来自专栏Golang语言社区

GO语言标准库概览

在Go语言五周系列教程的最后一部分中,我们将带领大家一起来浏览一下Go语言丰富的标准库。 Go标准库包含了大量包,提供了丰富广泛的功能特性。这里提供了概览仅仅是...

29340
来自专栏Elson's web

Promise 原理探究

你真的了解Promise吗?对我而言,除了知道如何使用then解决回调地狱以外,其他的还真的一知半解。虽然ES6的generator和ES7的async awa...

68670
来自专栏程序员宝库

Python爬虫抓取纯静态网站及其资源

前段时间需要快速做个静态展示页面,要求是响应式和较美观。由于时间较短,自己动手写的话也有点麻烦,所以就打算上网找现成的。

34820
来自专栏Golang语言社区

GO语言标准库概览

在Go语言五周系列教程的最后一部分中,我们将带领大家一起来浏览一下Go语言丰富的标准库。 Go标准库包含了大量包,提供了丰富广泛的功能特性。这里提供了概览仅仅是...

396100
来自专栏柠檬先生

Angularjs基础(二)

AngularJS 表达式   AngularJS 表达式写在双大括号内:{{expression}}   AngularJS 表达式把数据绑定到HTML,...

21560
来自专栏自动化测试实战

flask第二十三篇——模板【5】过滤器

24990
来自专栏生信宝典

Bash概论 - Linux系列教程补充篇

本篇是我最开始学习Linux命令时看的一篇帖子,最早见于ChinaUnix (这次查找其出处时发现2002年就有这篇)。学习过程中,遇到问题就查一下。这次看到,...

20670
来自专栏黄Java的地盘

eventEmitter3源码分析与学习

事件监听在前端的开发过程中是一个很常见的情况。DOM上的事件监听方式,让我们看到了通过事件的方式来进行具体的业务逻辑的处理的便捷。

17610

扫码关注云+社区

领取腾讯云代金券