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()); |