Android support-annotations 注解使用
Android 注解库依赖
Android-support-library
引入了新的注解库,包含很多有用的元注解,可以用来修饰代码提示。如果使用了 v4、v7、appcompat 的库,则内部已经引用过下面的依赖。
implementation 'com.android.support:support-annotations:28.0.0'
注解库元注解说明
依赖了上述 Android 注解库后,就可以使用下面的元注解了。
资源注解
@StringRes
用于指出一个 integer 的参数、成员变量或方法返回值是一个 string 资源的引用。示例:
//成员变量
@StringRes
int userId;
//参数
public void setUserId(@StringRes int userId) {
}
//方法返回值
public @StringRes int getUserId(){
// return R.string.app_name;
return userId;
}
举个例子,当 @StringRes 用作参数限定时,参数为 int 类型,正确情况下只能传 R.string.xx,如下图:
@StringRes如果直接传 int 数值,编译器会发出警告以提醒开发者注意编码的正确性。注意:即使编译器发出警告,仍然能忽略警告直接编译运行项目。
下面的代码是来自另一注解库的写法,
android-support-annotations
并不支持,不要弄混。@StringRes(R.string.text_name) String text;
来自依赖库:
annotationProcessor 'org.androidannotations:androidannotations:4.4.0' implementation 'org.androidannotations:androidannotations-api:4.4.0'
相似的,资源注解还支持以下资源类型:
@AnimatorRes、@AnimRes、@AnyRes、@ArrayRes、@AttrRes、@BoolRes、@ColorRes、@DimenRes、@DrawableRes、@FractionRes、@IdRes、@IntegerRes、@InterpolatorRes、@LayoutRes、@MenuRes、@PluralsRes、@RawRes、@StyleableRes、@StyleRes、@TransitionRes、@XmlRes
颜色注解
@ColorInt
用于指出被注解的元素是一个 int 颜色值,表示的是 AARRGGBB。
线程注解
指定方法运行在特定线程中。
@MainThread:被注解的方法应该只在主线程中被调用。
@WorkerThread:被注解的方法应该只在工作线程中被调用。
@UiThread:被注解的方法应该只在 UI 线程中被调用。
但是实际测试发现对于 @MainThread、@UiThread 俩个注解 ide 没有给出很好的警号,下面是图示,有知道原因的同学欢迎留言。
方法定义:
@MainThread
public void testMainThread(){
}
@UiThread
public void testUiThread(){
}
@WorkerThread
public void testWorkerThread(){
}
测试结果:
@xxxThread空注解
@Nullable 用来标记参数或返回值可以为 null;
@NonNull 用来标记参数或返回值不能为 null;
@NonNull
String nullString = "test";
public void testNull(@Nullable String key){
}
public @Nullable String testNull(){
return null;
}
public void testNonNull(@NonNull String key){
}
public @NonNull String testNonNull(){
return "test";
}
当出现错误使用时,会出现下面的黄色背景警告:
@NonNull但是需要注意,即使上述示例中出现了警告,也仍然能编译通过,所以 @Nullable、@NonNull 并非是安全的,它仅是编码时的一种提示。
样式注解
@IntDef @StringDef
相当于替换枚举。
@IntDef({SpecType.TYPE_ONE, SpecType.TYPE_TWO, SpecType.TYPE_THREE})
@Retention(RetentionPolicy.SOURCE)
public @interface SpecType {
int TYPE_ONE = 1;
int TYPE_TWO = 2;
int TYPE_THREE = 3;
}
//示例
public void setSpecType(@SpecType int type) {
}
同样,错误情况下,存在下划线警告仍然能编译通过,注解仅仅用来提示开发者编码的正确性,并非绝对安全。
值域注解
@Size @IntRange @FloatRange
指定元素的数值范围。
使用:
public void setValue(@IntRange(from = 0, to = 10) int v) {
}
public void setSize(@Size(min = 1) int v) {
//int 最小为 1
}
public void setSize(@Size(max = 5) String s) {
//string 的长度最大为 5
}
public void setSize(@Size(min = 1) List l) {
//集合至少有一个元素
}
public void setSize(@Size(2) int[] arr) {
//数组只能有俩个元素
}
测试结果:
@xxxRange测试发现 @IntRange 中,对于 int、集合,ide 没有给出正确的警告(也可能是理解、测试方式有误?),有清楚原因的小伙伴欢迎留言。
权限注解
@RequiresPermission
声明一个方法需要的权限。
@RequiresPermission(Manifest.permission.INTERNET)
public void testPermission(){
}
当 AndroidManifest 没有配置相应权限时会下划线警告。
重写注解
@CallSuper
用于提示重写的父类方法也必须调用。
使用:
public class Father {
@CallSuper
public void test(){
}
}
测试结果:
@CallSuper混淆注解
@Keep
保证代码不被混淆
总结
注解有以下三种类型:
类型 | 效果 | 用途 |
---|---|---|
RetentionPolicy.Source | 源码注解,Java 编译成 class 时注解被遗弃。 | 编码时检测,如 @Nullable |
RetentionPolicy.CLASS | 注解保留到 class 文件,但 JVM 加载 class 时遗弃,是默认生命周期。 | 编译时处理,如EventBus 3.0 编译时注解 |
RetentionPolicy.RunTime | 注解在运行时仍然存在。 | 动态注解,如 EventBus 2.0,或枚举替代 |
Android support-annotations 注解库更多的作用是协调开发(即上述源码注解或编译时注解),注解可以给予协作者一定的代码提示,使用它制定开发规则,以提升协作开发下代码的健壮性。另外需要注意的是,注解并非像 Java 强类型校验一样安全,即使存在告警也能编译通过并运行,所以兼容代码仍然需要。