Java 中有注解,Android 中也有注解,本文将介绍下 Android 的注解。这是探索注解系列文章的最后一篇:
探索注解之 APT 编译时处理注解, 解析 Butterknife 注解原理 (鸿神写编译时注解的文章,非常好,所以自己就不再重复写了)
引入注解库
Android 的注解库并没有包括在 framework 中,它被独立成一个单独的库。通常情况下,只需要编辑build.gradle
文件就可引入:
|
|
如果已经引入了appcompat
库的话,就不需要额外引入support-annotations
,因为appcompat
包含了注解库。
对于 Android 应用或者 Android Library 模块的话,上面的工作就可以引入注解库。如果想要在纯粹的 Java 模块中(即在 gradle 文件中apply plugin: 'java'
)引入注解库的话,还要显式地标明 SDK 的 repositories,因为注解库不在 jcenter 上(Android 的 gradle plugin 默认包含这个依赖,而 Java plugin 并没有)。
|
|
Null 相关注解
|
|
这两个注解可以修饰下面三种元素:
成员属性
方法参数
方法返回值
合理使用这两个注解可以增加代码的可读性,减少一些 NullPointerException。
@NonNull 注解检测生效的条件:
显式地使用 null
使用前已经判断了参数为 null
资源类型注解
Android 中所有的资源 id 都是 int 类型,所以代码期望 string id 但是容易传入 drawable id。而使用 @StringRes 注解的话,编译器就会帮我们检测,如果不是传入R.string
id 就会标注出来。
下面是 TextView 的一个例子:
|
|
Android 中的资源注解有::AnimRes, AnimatorRes, AnyRes, ArrayRes, AttrRes, BoolRes, ColorRes, DimenRes, DrawableRes, FractionRes, IdRes, IntegerRes, InterpolatorRes, LayoutRes, MenuRes, PluralsRes, RawRes, StringRes, StyleRes, StyleableRes, TransitionRes, XmlRes。
其中有个特殊的注解 @AnyRes 表示修饰的元素必须是资源类型,但具体是哪种类型不确定。在framework中有用到Resources#getResourceName(@AnyRes int resId)
。
IntDef/StringDef: 替代枚举
Enum 的内存占用是静态常量的 2 倍,Google 推荐使用IntDef
和StringDef
来代替枚举。
下面以 IntDef 说明下:
|
|
StringDef 的用法与 IntDef 类似,IntDef 还可以指定整型值作为标志位(即可以使用 | 和 & 操作符):
|
|
线程注解
Android 中有四个线程相关的注解:
@UiThread,通常可以等同于主线程,标明方法或者构造函数需要在 UiThread 执行,例如 View 类就使用这个注解
@MainThread,主线程
@WorkerThread,工作者线程,一般为后台线程,例如 AsyncTask 中的 doInBackground 方法
@BinderThread,标明方法必须要在 BinderThread 执行
AsyncTask 中的例子:
|
|
注意,下面这种情况不会出现错误提示
|
|
因为编译器的判断规则是,updateViews
的线程注解和run
方法的不一致才会提示。这里 run 方法没有线程注解,所以不会提示。
RGB Color 值
上面提到了可以使用@ColorRes
来限定颜色资源 id,但是当我们需要一个实际的 RGB 或 ARGB 的颜色值,就需要用@ColorInt
注解了。
TextView 中的例子:
|
|
值约束:@Size、@IntRange、@FloatRange
对于数组,集合或者字符串,可以使用@Size
来约束长度或者大小,下面有几个例子:
数组长度必须为 2: @Size(2)
集合不能为空: @Size(min = 0)
字符串最多只能有 23 个字符: @Size(max = 23)
数组的长度必须为 3 的倍数: @Size(multiple = 3)
IntRange 和 FloatRange 是用来限定区间范围的,如果参数或变量为 float 或者 double 类型,可以使用@FloatRange
约束取值范围:
|
|
权限相关
@RequiresPermission
注解用来表明需要的一个或多个权限。
需要一个单独权限:
|
|
需要多个权限的任意一个:
|
|
需要多个权限:
|
|
需要单独的读权限或写权限:
|
|
重写方法:@CallSuper
重写的方法必须要调用 super 方法。
使用@CallSuper
注解,可以强制在重写时必须调用父类的方法,例如 Activity 的onCreate
方法。
返回值:@CheckResult
@CheckResult
只能注解方法,如果执行一个方法,却没有使用返回值,就会有错误提示,这也说明没有正确地使用该方法。
|
|
@Keep
在 Android 编译生成 APK 的环节,通常需要设置minifyEnabled
为 true 来混淆代码和删除无用代码。
但是但是出于某一些目的,我们需要不混淆某部分代码或者不删除某处代码,除了配置复杂的 Proguard 文件之外,我们还可以使用 @Keep 注解。
|
|
注意需要 Gradle plugin 版本在 2.2 以上。
参考文章: