1. 引入Annotations库
直接修改build.gradle配置文件,添加该库的引用。例如:
也可以通过Android Studio的Project Structure (File → Project Structure,Dependencies)添加引用。
? | Annotations库并没有被上传到jcenter(其它Support库也是), 而是存放于Android SDK中的一个本地maven库中。 因此,如果需要在Java模块中使用Annotations库,则需要添加Support库的maven库: maven { url '<your-SDK-path>/extras/android/m2repository' } 。 |
2. annotations介绍
2.1. null相关
用于修饰Method的参数和返回值,以便IDE对相关的约束进行检查。列举如下:
-
@Nullable 表示允许为null
-
@NonNull 表示不允许为null
从官网抄一段例子:
需要注意的是,对于一个变量或者返回值,除了可指定@NonNull和@Nullable之外, 还有第三种状态,即“未指定”。
⚠️ | 当一个方法可能会返回null时,我们有两种选择: 一是指定@Nullable,二是什么都不指定。 如果打算指定为@Nullable,这意味着所有调用者都需要检查返回值是否为null。 也许,这并不是期望的行为,可能更好的选择是什么都不指定。 |
2.2. 资源类型相关
用于修饰对资源ID的相关引用,以便IDE对相关的资源类型进行检查。列举如下:
-
@AnimRes
-
@AnimatorRes
-
@AnyRes
-
@ArrayRes
-
@AttrRes
-
@BoolRes
-
@ColorRes
-
@DimenRes
-
@DrawableRes
-
@FractionRes
-
@IdRes
-
@IntegerRes
-
@InterpolatorRes
-
@LayoutRes
-
@MenuRes
-
@PluralsRes
-
@RawRes
-
@StringRes
-
@StyleRes
-
@StyleableRes
-
@XmlRes
从官网抄一段例子:
2.3. 常量定义相关
2.3.1. @IntDef
我们经常使用int来定义一些常量来代替使用enum,可以使用这个annotation来添加相关的约束。
还是搬官网的例子:
再搬一个例子,关于flags类型(可进行异或运算)的常量定义:
2.3.2. @StringDef
该annotation用于修饰字符串常量,用法跟前面的@IntDef类似。
2.4. 线程相关
从Support库v22.2开始,加入了几个线程相关的annotations:
-
@MainThread 指定在主线程中执行
-
@UiThread 指定在UI线程中执行
-
@WorkerThread 指定在非UI线程中执行
-
@BinderThread 指定在Binder线程中执行
如果某个方法仅在某一类线程中调用,那么可以为其添加上面的annotation; 如果某个类的所有方法都仅在某一类线程中调用,那么可以为类添加线程annotation。
2.4.1. @MainThread vs @UiThread
一个进程中,仅有一个主线程。 @MainThread就是指这个主线程,同时这个主线程也是@UiThread。
理论上,在一个进程中,可以有多个@UiThread,虽然很少见。
在实际使用中,可以遵循如下原则:
-
生命周期相关的使用@MainThread(例如,AsyncTask#onProgressUpdate方法)
-
View体系使用@UiThread
Android Studio、Android Lint等工具会把两者认为是可互换的, 因此不会区分两者。
2.5. 接受ARGB颜色值
如果一个方法的参数接受颜色资源ID,则可以使用前面的@ColorRes; 如果接受颜色的ARGB值,则可以使用@ColorInt。
2.6. 限定参数值范围
2.6.1. @FloatRange
对于float或double类型的参数,可以使用@FloatRange来指定取值范围:
2.6.2. @IntRange
对于int或long类型的参数,可以使用@IntRange来指定取值范围。
2.6.3. @Size
如果对数组、集合或者String的元素个数有所约束,则可以使用@Size:
-
@Size(min=N) 指定元素最小个数为N
-
@Size(max=N) 指定元素最大个数为N
-
@Size(N) 精确指定元素个数为N
-
@Size(multiple=N) 指定元素个数为N的倍数
2.7. 指定权限
可以通过@RequiresPermission来指定调用者需要拥有的权限, 一般只有系统代码中才会用得到。
2.8. 强制调用基类方法
如果允许一个方法被重写,但要求在子类的重写方法中调用基类的方法, 则可以使用@CallSuper:
2.9. 强制使用返回值
@CheckResult 适用于必须使用返回值的场景。例如:
2.10. 测试可见
当仅为了测试,把类、方法或者字段的可见性放大时,可用@VisibleForTesting来修饰。
2.11. 混淆保留
同ProGuard的“-keep”,用于在代码混淆时阻止某些代码被混淆。
⚠️ | 此功能还在开发中,目前不可用。 |
3. 结语
在项目中支持这些annotation是比较繁琐的,就像为项目添加单元测试的支持一样。 但同样的,如果能够在项目中支持这些annotation,其带来的质量提升是很明显的。 特别是对于library project项目,建议在代码规范予以支持。