Android项目规范
命名规范
通用命名规范
- 如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。(Builder、Factory、Proxy、Adapter、Wrapper)
- 任何命名不能以
下划线或者符号开头。 - 任何命名严禁直接使用
中文的方式。纯拼音的方式应尽量避免使用,使用完整的单词组合来表达其意。 - 杜绝完全不规范的缩写,避免望文不知义(多个单词缩写不要只提取首字母)。
包命名规范
- 反域名命名规则
.之间有且仅有一个自然语义的英语单词,可以使用下划线。
类,抽象类,接口命名规范
- 名词
- 类名使用
UpperCamelCase(大驼峰)风格 - 抽象类命名使用
Abstract或Base开头 - 接口类命名使用以
listener,able,ible,callback等类似功能性词缀结尾(单独文件时使用,变量命名则遵循变量名规范) - 异常类命名使用
Exception、Throwable结尾。 - 测试类命名以要测试的类的名称开始,以
Test结尾 - dataClass后缀为Bean
- 枚举类后缀为Enum
- 数据库的数据类后缀为Entity
- dataClass进行类转换或者提取信息的工具类后缀为Converter
函数命名规范
- 动词或动名词
- 方法名、参数名、成员变量、局部变量都统一使用
lowerCamelCase(小驼峰)风格
变量命名规范
- 不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。(单个文件内的boolean、int类型可以使用,加上注释,但是不建议)
- 在 long 或者 Long 赋值时,数值后使用大写的 L,不能是小写的 l,小写容易跟数字1 混淆,造成误解。
- 不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
- 如果变量值仅在一个固定范围内变化用 enum 类型来定义。
- 枚举成员名称需要全大写,单词间用下划线隔开。
- 类中控件名称尽量和xml控件id保持一致
- 公开常量应定义为静态final,名称全部大写.
例如: ```const val ACTION_MAIN = ”android.intent.action.MAIN”``
安卓相关命名规范
Java类命名
| 类 | 格式 | 示例 |
|---|---|---|
| Activity | xxx描述+Activity | FindActivity |
| Fragment | xxx描述+Fragment | SearchFragment |
| Adapter | xxx描述+Adapter | SearchAdapter |
| Model | xxx描述+Model | SearchModel |
| ViewModel | xxx描述+ViewModel | SearchViewModel |
| Service | xxx描述+Service | ImService |
| BroadcastReceiver | xxx描述+Receiver | NetworkReceiver |
| 基类 | Base+父类命名 | BaseActivity |
资源文件命名规范
- 命名以使用的控件为前缀,后面加上描述,中间以下划线分隔
- lib库的资源在以上基础上加上模块前缀,防止资源名称相同编译不通过
控件命名
| 控件 | 缩写 |
|---|---|
| TextView | tv |
| EditText | et |
| Button | bt |
| ImageButton | ib |
| LinearLayout | ll |
| RelativeLayout | rl |
| RecyclerView | rv |
| ScrollView | sv |
| ConstraintLayout | cl |
- layout
| 布局类型 | 命名格式 |
|---|---|
| Activity布局 | module_activity_xxx |
| fragment布局 | module_fragment_xxx |
| dialog布局 | module_dialog_xxx |
| 可include布局 | module_include_xxx |
| recyclerView布局 | module_recycler_item_xxx |
drawable
| drawable | 命名格式 |
|---|---|
| icon | module_ic_xxx |
| selector | module_selector_xxx |
| shape | module_shape_xxx |
| menu | module_menu_xxx |
selector
- 多状态的,应在命名中体现
| selector | 命名格式 |
|---|---|
| normal | xx_normal |
| pressed | xx_pressed |
| focused | xx_focused |
| selected | xx_selected |
strings
- strings 见名知意即可
colors
dimens
- length_value 代表一般长度(暂时用不到)
- font_value 代表字体
- (UI规范类的暂时没有)
控件ID
控件名+功能(全称也行)
| 控件 | 缩写 |
|---|---|
| LinearLayout | ll |
| RelativeLayout | rl |
| TextView | tv |
| Button | bt |
| ImageButton | iv |
| ImageView | iv |
| CheckBox | cb |
| RadioButton | rb |
| DatePicker | dp |
| EditText | et |
| TimePicker | tp |
| ProgressBar | pb |
| SeekBar | sb |
| AutoCompleteTextView | actv |
| ZoomControls | zc |
| VideoView | vv |
| WdbView | wv |
| RantingBar | rb |
| Tab | tab |
| Spinner | spn |
| Chronometer | cmt |
| ScrollView | sv |
| TextSwitch | ts |
| ImageSwitch | is |
| listView | lv |
| ExpandableList | el |
| MapView | mapView |
编码要求
通用编码要求
- 代码格式化用开发工具默认的风格
- 单个方法的总行数尽量不超过 100 行
- 不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。任何情形,没有必要插入多个空行进行隔开。
- 过时的类和方法必须加@Deprecated 注解.(kotlin怎么处理需要再看一下,禁用官方已经Deprecated的类和方法,除非低版本适配)
- 类内方法定义的顺序依次是:功能相近活着引用的方法放到一起。
- 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
- 避免黄色警告。
- 每一个module都要有自己的README.md文件。
Kotlin相关编码要求
- 在一个 when 块内,都必须包含一个 else 语句并且放在最后,即使空代码。
- 多个字符串动态拼接的时候,使用StringBuilder 的 append 方法进行扩展。避免造成内存资源浪费。
类成员与方法访问控制
- 如果不允许外部直接通过
new来创建对象,那么构造方法必须是private。 - 工具类不允许有
public或default构造方法,禁用Utils,要使用Ext,Converter,顶层声明 - 类非
static成员变量并且与子类共享,必须是protected。 - 类非
static成员变量并且仅在本类使用,必须是private。 - 类
static成员变量如果仅在本类使用,必须是private。 - 若是
static成员变量,考虑是否为const val。 - 类成员方法只供类内部调用,必须是
private。 - 类成员方法只对继承类公开,那么限制为
open。
注释规范
- 类、类属性、类方法的注释必须使用 Javadoc 规范,使用
/**内容*/格式,不得使用// xxx方式。 - 所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释,指出该方法做什么事情,实现什么功能。
- 所有的类都必须添加创建者和创建日期和功能.
- 方法内部单行注释,在被注释语句上方另起一行,使用
//注释。方法内部多行注释使用/* */注释 - 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
- 注释中专有名词与关键字保持英文原文即可。
- 修改代码时也应该同步修改注释
注释模板
- 统一修改成以下注释模版,在创建文件时必须加上这个
1
2
3
4
5
6/**
* @Description: TODO
* @Author: ${USER}
* @Date: ${DATE} ${TIME}
* @Gmail: 你的这个邮箱 @tron.network
*/
Android相关编码要求(优化项)
- 避免在
Service#onStartCommand()/onBind()方法中执行耗时操作,如果确实有需求,应改用IntentService或采用其他异步机制完成。 - 避免在
BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作,应该创建IntentService完成,而不应该在BroadcastReceiver内创建子线程去做。 - 对于只用于应用内的广播,优先使用
LocalBroadcastManager来进行注册和发送,LocalBroadcastManager安全性更好,同时拥有更高的运行效率。 Activity或者Fragment中动态注册BroadCastReceiver时,registerReceiver()和unregisterReceiver()要成对出现。- 释放资源的实际可以结合实际情况在
onStop执行,在Ondestroy中执行时机比较晚 - 源文件统一采用
UTF-8的形式进行编码。 - 禁止在设计布局时多次设置子
view和父view中为同样的背景造成页面过度绘制,推荐将不需要显示的布局进行及时隐藏,推荐使用约束布局 - 文本大小使用单位
sp,view大小使用单位dp。 - 尽少使用
AnimationDrawable会把所有图片都加载到内存,注意内存溢出 - 子线程中不能更新界面,更新界面必须在主线程中进行,网络操作不能在主线程中调用。
- 新建线程时,定义能识别自己业务的线程名称,便于性能优化和问题排查。
- 任何时候不要硬编码文件路径,请使用
Android文件系统API访问。 - 当使用外部存储时,必须检查外部存储的可用性。
- 应用间共享文件时,不要通过放宽文件系统权限的方式去实现,而应使用
FileProvider。 SharedPreference中只能存储简单数据类型(int、boolean、String等),复杂数据类型建议使用数据库等其他方式存储。- 数据库
Cursor必须确保使用完后关闭,以免内存泄漏。 - 多线程操作写入数据库时,需要使用事务,以免出现同步问题。
- 在
Activity.onPause()或Activity.onStop()回调中,关闭当前activity正在执行的的动画。 - 在有强依赖
onAnimationEnd回调的交互时,如动画播放完毕才能操作页面 ,onAnimationEnd可能会因各种异常没被回调,建议加上超时保护或通过postDelay替代onAnimationEnd。 - 将
android:allowbackup属性设置为false,防止adb backup导出数据。 - 应用发布前确保
android:debuggable属性设置为 false。
其他编码要求
- 砍掉的需求和无用代码以及注释必须及时清除
- 一些空指针异常不要用
try catch - 应用中不允许直接调用系统的类打印日志
- 正式环境禁止输出日志
- 严格按照MVVM模型开发
- 使用响应式编程范式开发
- 使用第三方
SDK的时候 应避免直接依赖 需要写一层中间件(除了长期不变的主流框架不需要写中间件)
关于序列化
- 如果是持久化保存用
Serializable序列化 - 如果是只是在内存中使用 用
Parcelable序列化
关于单例模式
- 注意是否有高并发
代码检查
- 类,抽象类,接口,泛型必须要按照注释模版进行注释
没有注释的不予通过. - 拼写错误必须处理
typo TODO
代码规范写法,否则会有@SuppressLint警告
@SuppressLint(“DrawAllocation”)
原因:我们都知道View及其子类的OnDraw(Canvas canvas)方法会实时调用来更新界面的,然而有时我们会在onDraw(Canvas canvas)方法中实例化对象(如Paint paint=new Paint()),这样就会影响我们程序的效率。
解决办法:将这些对象改为类的成员变量。
@SuppressWarnings(“rawtypes”)和@SuppressWarnings({ “unchecked”, “rawtypes” })
不规范写法:
1 | Class clazz = Class.forName(“android.view.Display”); |
正确写法:
1 | Class<?> clazz = Class.forName("android.view.Display"); |
@SuppressLint(“HandlerLeak”)
原因:Handler在Android中用于消息的发送与异步处理,常常在Activity中作为一个匿名内部类来定义,此时Handler会隐式地持有一个外部类对象(通常是一个Activity)的引用。当Activity已经被用户关闭时,由于Handler持有Activity的引用造成Activity无法被GC回收,这样容易造成内存泄露。
解决办法:将其定义成一个静态内部类(此时不会持有外部类对象的引用),在构造方法中传入Activity并对Activity对象增加一个弱引用,这样Activity被用户关闭之后,即便异步消息还未处理完毕,Activity也能够被GC回收,从而避免了内存泄露。
静态内部类,持有外部类的弱引用。这是最标准的写法。
1 | private MyHandler handler = new MyHandler(this); |
另一种情况:
1 | //不规范的写法 |
@SuppressLint(“SimpleDateFormat”)
不规范写法:
1 | SimpleDateFormat format = new SimpleDateFormat(pattern); |
正确写法:
1 | SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault()); |
@SuppressLint(“DefaultLocale”)
不规范写法:
1 | String lower = string.toLowerCase(); |
正确写法:
1 | String lower = string.toLowerCase(Locale.getDefault()); |