Android 注解指南
来源 https://juejin.im/entry/58fc7ca744d9040069e65197
日常开发中,注解能够帮助我们写出更好更优秀的代码,为了更好地支持 Android 开发,在已有的 android.annotation 基础上,Google 开发了 android.support.annotation 扩展包,共计50个注解,帮助开发者们写出更优秀的程序。
官网链接:developer.android.google.cn/reference/a…、developer.android.google.cn/reference/a…
一览
注解名 | 释义 | 修饰类型 |
---|---|---|
AnimatorRes | 用于描述一个整型的参数或字段,或者是一个期望返回 animator 资源引用的方法(例如:android.R.animator.fade_in) | 参数、字段、方法 |
AnimRes | 用于描述一个整型的参数或字段,或者是一个期望返回 anim 资源引用的方法(例如:android.R.anim.fade_in) | 参数、字段、方法 |
AnyRes | 用于描述一个整型的参数或字段,或者是一个期望返回任意资源引用的方法 | 参数、字段、方法 |
AnyThread | 被注解的元素可以在任意线程被调用 | 方法、构造器、类、接口、枚举 |
ArrayRes | 用于描述一个整型的参数或字段,或者是一个期望返回 array 资源引用的方法(例如:android.R.array.phoneTypes) | 参数、字段、方法 |
AttrRes | 用于描述一个整型的参数或字段,或者是一个期望返回 attr 资源引用的方法(例如:android.R.attr.action) | 参数、字段、方法 |
BinderThread | 用于描述一个方法、构造器、类、接口、枚举应该运行在 binder 线程 | 方法、构造器、类、接口、枚举 |
BoolRes | 用于描述一个整型的参数或字段,或者是一个期望返回 boolean 资源引用的方法 | 参数、字段、方法 |
CallSuper | 用于描述子类方法,希望它们重写父类方法时也要通过 super.() 调用父类方法 |
方法 |
CheckResult | 用于描述一个方法,如果它的返回值被忽略了,那么就会报错 | 方法 |
ColorInt | 用于描述一个整型的参数或字段,或者是一个期望返回 int 类型颜色值的方法 | 参数、字段、方法 |
ColorLong | 用于描述一个整型的参数或字段,或者是一个期望返回 long 类型颜色值的方法 | 参数、字段、方法 |
ColorRes | 用于描述一个整型的参数或字段,或者是一个期望返回 color 资源引用的方法(例如:android.R.color.black) | 参数、字段、方法 |
DimenRes | 用于描述一个整型的参数或字段,或者是一个期望返回 dimension 资源引用的方法(例如:android.R.dimen.app_icon_size) | 参数、字段、方法 |
Dimension | 用于描述一个整型的参数或字段,或者是一个期望返回 dimension 的方法 | 参数、字段、方法、注解 |
DrawableRes | 用于描述一个整型的参数或字段,或者是一个期望返回 drawable 资源引用的方法(例如:android.R.attr.alertDialogIcon) | 参数、字段、方法 |
FloatRange | 描述一个参数、字段或方法的返回值是一个指定范围内的 float 或 double 类型的值 | 参数、字段、方法 |
FractionRes | 用于描述一个分数类型的参数或字段,或者是一个期望返回 fraction 资源引用的方法 | 参数、字段、方法 |
HalfFloat | 用于描述一个半精度类型的参数或字段,或者是一个期望返回半精度值的方法 | 参数、字段、方法 |
IdRes | 用于描述一个整型的参数或字段,或者是一个期望返回 id 资源引用的方法(例如:android.R.id.copy) | 参数、字段、方法 |
IntDef | 用于描述一个注解,然后再用这个被描述的注解去描述一个整形的参数或字段,或者是一个期望返回值是显示声明常量之一的方法 | 注解 |
IntegerRes | 用于描述一个整型的参数或字段,或者是一个期望返回 integer 资源引用的方法(例如:android.R.integer.config_shortAnimTime) | 参数、字段、方法 |
InterpolatorRes | 用于描述一个整型的参数或字段,或者是一个期望返回 integer 资源引用的方法(例如:android.R.interpolator.cycle) | 参数、字段、方法 |
IntRange | 描述一个参数、字段或方法的返回值是一个指定范围内的 int 类型的值 | 参数、字段、方法 |
Keep | 被注解的元素不会被混淆 | 包、参数、字段、方法、类、接口、枚举、注解、构造器 |
LayoutRes | 用于描述一个整型的参数或字段,或者是一个期望返回 layout 资源引用的方法(例如:android.R.layout.list_content) | 参数、字段、方法 |
MainThread | 被注解的元素只能在主线程被调用 | 方法、构造器、类、接口、枚举 |
MenuRes | 用于描述一个整型的参数或字段,或者是一个期望返回 menu 资源引用的方法(例如:android.R.menu.content) | 参数、字段、方法 |
NonNull | 用于描述一个参数或字段、或者一个方法的返回值不为空 | 参数、字段、方法 |
Nullable | 用于描述一个参数或字段、或者一个方法的返回值可为空 | 参数、字段、方法 |
PluralsRes | 用于描述一个整型的参数或字段,或者是一个期望返回 plurals 资源引用的方法(例如:android.R.plurals.ph) | 参数、字段、方法 |
Px | 用于描述一个整型的参数或字段,或者是一个期望返回像素尺寸的方法 | 参数、字段、方法 |
RawRes | 用于描述一个整型的参数或字段,或者是一个期望返回 raw 资源引用的方法(例如:android.R.raw.ph) | 参数、字段、方法 |
RequiresApi | 被注解的元素只能在被给的 API 版本或更高情况下才能被调用 | 类、接口、枚举、方法、构造器、字段 |
RequiresPermission | 被注解的元素需要或者可能需要一个或多个权限 | 注解、方法、构造器、字段 |
RequiresPermission.Read | ||
RequiresPermission.Write | ||
RestrictTo | 被注解的元素只能在特定的范围内被访问 | 注解、类、接口、枚举、方法、构造器、字段、包 |
Size | 被注解的元素需要提供其大小或长度 | 参数、字段、方法、注解 |
StringDef | 用于描述一个注解,然后再用这个被描述的注解去描述一个 string 类型的参数或字段,或者是一个期望返回值是显示声明常量之一的方法 | 注解 |
StringRes | 用于描述一个整型的参数或字段,或者是一个期望返回 string 资源引用的方法(例如:android.R.string.ok) | 参数、字段、方法 |
StyleableRes | 用于描述一个整型的参数或字段,或者是一个期望返回 styleable 资源引用的方法(例如:android.R.styleable.TextView_text) | 方法、参数、字段 |
StyleRes | 用于描述一个整型的参数或字段,或者是一个期望返回 style 资源引用的方法(例如:android.R.style.TextAppearance) | 方法、参数、字段 |
TransitionRes | 用于描述一个整型的参数或字段,或者是一个期望返回 transitionRes 资源引用的方法(例如:android.R.transition.fade) | 方法、参数、字段 |
UiThread | 被注解的元素只能在主线程被调用 | 方法、构造器、类、接口、枚举 |
WorkerThread | 被注解的元素只能在工作线程被调用 | 方法、构造器、类、接口、枚举 |
XmlRes | 用于描述一个整型的参数或字段,或者是一个期望返回 xml 资源引用的方法(例如:android.R.xml.test) | 参数、字段、方法 |
SuppressLint | Lint 静态检测工具将会忽略被注解元素的警告 | 类、字段、方法、参数、构造器 |
TargetApi | Lint 静态检测工具将会以指定 API 版本对待被注解元素 | 类、接口、枚举、方法、构造器 |
示例详解
AnimatorRes
1.在 res 文件夹下创建 animator 子文件夹
2.在 animator 文件夹下创建 scale.xml 文件
<set xmlns:android="http://schemas.android.com/apk/res/android"></set>
3.在需要的地方如下调用:
@AnimatorRes
public int returnAnimator() {
return R.animator.scale;
}
如果将 return R.animator.scale;
改成 return 1;
或 return R.string.test;
等均会报错。
AnimRes
1.在 res 文件夹下创建 anim 子文件夹
2.在 anim 文件夹下创建 scale.xml 文件
<set xmlns:android="http://schemas.android.com/apk/res/android"></set>
3.在需要的地方如下调用:
@AnimRes
public int returnAnim() {
return R.anim.scale;
}
如果将 return R.anim.scale;
改成 return 1;
或 return R.string.test;
等均会报错。
AnyRes
在需要的地方如下调用:
@AnyRes
public int returnAny() {
return 1;
}
如果能提前知道返回值的具体资源类型,建议将 AnyRes
换成具体的资源类型,如 StringRes
或 DrawableRes
等。
AnyThread
在需要的地方如下调用:
@AnyThread
public void test() {
//.....
}
ArrayRes
1.在 values 文件夹下创建 arrays.xml 文件
2.在 arrays.xml 文件中添加名为 names 的子项
<resources>
<array name="names">1, 2, 3</array>
</resources>
3.在需要的地方如下调用:
@ArrayRes
public int returnArray() {
return R.array.names;
}
如果将 return R.array.names;
改成 return 1;
或 return R.string.test;
等均会报错。
AttrRes
1.在 attrs.xml 文件中添加名为 CircleView 的子项
<resources>
<declare-styleable name="CircleView">
<attr name="circle_color" format="color"/>
</declare-styleable>
</resources>
2.在需要的地方如下调用:
@AttrRes
public int returnAttr() {
return R.attr.circle_color;
}
如果将 return R.attr.circle_color;
改成 return 1;
或 return R.string.test;
等均会报错。
BinderThread
1.表明指定的元素只能运行在 Binder 线程:
@BinderThread
public void test() {
// ...
}
BoolRes
1.在 values 文件夹下创建 bools.xml 文件
2.在 bools.xml 文件中添加名为 isHide 的子项
<resources>
<bool name="isHide">true</bool>
</resources>
3.在需要的地方如下调用:
@BoolRes
public int returnBool() {
return R.bool.isHide;
}
如果将 return R.bool.isHide;
改成 return 1;
或 return R.string.test;
等均会报错。
CallSuper
1.在 BaseActivity 中创建一个 init()
方法,我们在其中初始化一些 Activity 共有的初始化操作:
public class BaseActivity extends AppCompatActivity {
// ...
@CallSuper
public void init() {
// Activity 共有的初始化操作...
}
}
2.在具体 Activity 中继承 BaseActivity 并调用 init()
完成初始化操作:
public class MainActivity extends BaseActivity {
// ...
@Override
public void init() {
// super.init();
}
}
如果在 init()
方法中不通过 super.init()
等方式调用父类方法,那么就会报一个 warning,编译器将会建议你调用 super.init()
。
CheckResult
1.创建一个 add()
方法:
@CheckResult
public int add() {
return 666;
}
2.调用该方法的地方不能忽略它的返回值:
add(); // error
int num = add(); // ok
ColorInt
ColorLong
ColorRes
1.在 colors.xml 下添加名为 colorAccent 的子项
<resources>
<color name="colorAccent">#FF4081</color>
</resources>
2.在需要的地方如下调用:
@ColorRes
public int returnColorRes() {
return R.color.colorAccent;
}
如果将 return R.color.colorAccent;
改成 return 1;
或 return R.string.test;
等均会报错。
DimenRes
1.在 dimens.xml 下添加名为 textview_height 的子项
<resources>
<dimen name="textview_height">25dp</dimen>
</resources>
2.在需要的地方如下调用:
@DimenRes
public int returnDimenRes() {
return R.dimen.textview_height;
}
如果将 return R.dimen.textview_height;
改成 return 1;
或 return R.string.test;
等均会报错。
Dimension
1.在需要的地方如下调用:
@Dimension(unit = Dimension.DP)
public int returnDimenRes() {
return 666;
}
注:该注解仅表明希望该方法返回的是一个 DP 的值,而返回值本身和 DP 无关
DrawableRes
1..在 drawable.xml 文件中添加名为 btn_test 的子项
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_focused"
android:state_window_focused="true"/>
<item android:drawable="@drawable/btn_normal"/>
</selector>
3.在需要的地方如下调用:
@DrawableRes
public int returnDrawRes() {
return R.drawable.btn_test;
}
如果将 return R.drawable.btn_test;
改成 return 1;
或 return R.string.test;
等均会报错。
FloatRange
1.用该注解所标记的元素只能返回指定范围内的浮点型数字,例如:
@FloatRange(from = -0.5F, to = 0.5F)
public float returnFloat() {
// return 0.8F; // error
return 0.2F; // ok
}
FractionRes
同 ColorRes 等。
IdRes
同 ColorRes 等。
IntDef
1.用该注解修饰一个注解:
@IntDef({LAST, NOW, NEXT})
@Retention(RetentionPolicy.SOURCE)
public @interface Year {
int LAST = 2016;
int NOW = 2017;
int NEXT = 2018;
}
2.再用被修饰的注解去注解指定元素:
@Year
public int returnYear() {
// return 666; // warning
return Year.LAST; // ok
}
IntegerRes
同 BoolRes 等。
InterpolatorRes
同 ColorRes 等。
IntRange
Keep
1.对于不希望被混淆的代码我们使用该注解:
@Keep
public void test() {
// ...
}
LayoutRes
同 ColorRes 等。
MainThread
同 BinderThread,表指定元素只能运行在主线程。
MenuRes
同 ColorRes 等。
NonNull
1.如果被注解的元素不可以取空值的话,我们使用该注解:
public Intent start2Activity(@NonNull String data) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("DATA", data);
return intent;
}
2.在调用该方法处如果我们传入 null 作为参数编译器将会给出 warning:
public void test() {
start2Activity(null); //warning,passing ‘null‘ argument to paramter annotated as @NonNull
}
Nullable
同 NonNull,意义相反,表被注解的元素可为空。
PluralsRes
同 BoolRes 等。
Px
实际等同于 Dimension 中 unit 取 PX 时的意义。
RawRes
同 BoolRes 等。
RequiresApi
1.当你使用的代码(例:API 11)不支持你当前所支持的最低版本(例:API 10)时,使用该注解注明:
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
2.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
所支持最低版本为 API 11,如果你的项目最低兼容到11以下的版本,那么编译器将会给出 warning,解决方法有三:
-
使用 RequiresApi 注解:
@Override @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) protected void onCreate(Bundle savedInstanceState) { getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
-
使用 Target 注解:
@Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) protected void onCreate(Bundle savedInstanceState) { getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
-
使用 if 包裹相应代码块:
@Override protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
注:网上大篇文章提到使用 RequiresApi 或 Target 注解能够解决低版本兼容问题,实际上它只是作为一个对程序员的提醒,告诉程序员这块代码只有在指定版本及以上才能使用,而并不是也不能用来解决兼容问题,指定代码块在低于指定版本上是不会运行的!
RequiresPermission
1.表注解的元素需要相应的权限:
@RequiresPermission(Manifest.permission.INTERNET)
private void netOperation() {
}
2.如果你的项目没有在 AndroidMenifest.xml 中声明相应的权限,那么调用该方法的地方将会抛出 Missing permissions required by MainActivity.netOperation:android.permission.INTERNET
warning,所以同样的,这个注解只是告诉程序员指定的元素需要某个权限,而不代表使用了该注解后就不需要注册权限。
RequiresPermission.Read
RequiresPermission.Write
RestrictTo
1.该注解用于想要指定访问元素权限的范围,例如我们在 BaseActivity 中对 init()
方法使用该注解:
@RestrictTo(RestrictTo.Scope.SUBCLASSES)
public void init() {
}
2.这是限定了该方法只能由 BaseActivity 子类才能访问到,如果是非子类访问,则会被编译器抛出 BaseActivity.int() can only be called from subclass
warning。
注:除 RestrictTo.Scope.SUBCLASSES
之外,还有其它几种枚举类型,详情可自行查看源码
Size
1.常用于限定数组大小的场合:
public @Size(2) int[] returnArr() {
int[] arr = new int[3];
int[] array = new int[2];
// return arr; // Size must be exactly 2.
return array; // ok
}
StringDef
同 IntDef。
StringRes
同 ColorRes 等。
StyleableRes
同 ColorRes 等。
StyleRes
同 ColorRes 等。
TransitionRes
同 ColorRes 等。
UiThread
同 BinderThread,表指定元素只能运行在 UI 线程。
WorkerThread
同 BinderThread,表指定元素只能运行在工作线程。
XmlRes
同 ColorRes 等。
SuppressLint
1.在想要屏蔽 Lint 静态检测工具的提示的地方添加该注解:
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// ...
}
};
TargetApi
见 RequiresApi。
============= End