- Android开发中大量的使用了注解,开源框架也大量使用,我们自己虽然自定义的注解不多,但也要了解基本的知识。
1.注解的定义
- Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 注解是元数据的一种形式,提供有关
于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。
2.注解是什么样的
- Java中所有的注解,默认实现 “Annotation ”接口
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
- 平时我们见到的最多就是重写注解吧,只要子类重写了父类的方法,都会出现这个注解。

- 看看这个 “@Override” 源码,注解的写法是 “@interface” ,跟接口有没有很像?,但前面多了一个 “ @” 符号
- 而且这个注解上面还有注解,这就是元注解

3.注解的分类以及作用
- 我这里整理了一些,自己写注解,不熟悉就翻来看看,用的多久熟悉了

4.注解写法
- 只有一个默认参数value 时,可以不写参数“key = ”,以下两种写法一样样效果
@Target({ElementType.TYPE,ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int value();
}
@TestAnnotation(111)
private int num1;
@TestAnnotation(value = 111)
private int num2;
- 如果要传入的参数不止一个,那么 “value = 111” 就一定要写全
- 如果有“default”默认参数了,就可以不用传参
- “default”也可以再传参覆盖原来的值
@Target({ElementType.TYPE,ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int value();
String data1();
String data2() default "222";
}
@TestAnnotation(value = 111,data1 = "111")
private int num1;
@TestAnnotation(value = 111,data1 = "111",data2 = "333")
private int num2;
5.注解使用
5.1 过时标记
- 过时标记“ @Deprecated”,是Java自带的,这个注解标记过的,都会划上横线,就是不推荐在使用了

5.2 语法检查
- 语法检查注解“@IntDef”,限制了参数类型,可以用来替代枚举类型
- Android中还有很多 @DrawableRes、@IdRes、@StringRes、@AnimRes等等,后面带上“Res”就是限制传入的参数类型了
public class WeekDay {
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@IntDef({MONDAY, TUESDAY, WEDNESDAY})
public @interface WeekDayAnnotation {
}
}

5.3 findViewById
- 不需要重复写findViewById,直接给控件加上注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
@IdRes int value();
}
public class InjectViewUtils {
public static void injectView(Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(InjectView.class)) {
InjectView injectView = field.getAnnotation(InjectView.class);
int id = injectView.value();
View view = activity.findViewById(id);
field.setAccessible(true);
try {
field.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
@InjectView(R.id.tvTest)
private TextView tvTest;
@InjectView(R.id.tvTest2)
private TextView tvTest2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectViewUtils.injectView(this);
}
5.4 View的Onclick
- 不需要拿到View,也不用写View的Onclick监听,直接加注解,省事
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectOnClick {
@IdRes int[] value();
}
public class OnClickUtils {
static public void inject(final Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (final Method method : methods) {
if (method.isAnnotationPresent(InjectOnClick.class)) {
InjectOnClick injectOnClick = method.getAnnotation(InjectOnClick.class);
int[] ids = injectOnClick.value();
method.setAccessible(true);
for (int id : ids) {
activity.findViewById(id).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(activity);
} catch (Exception e) {
e.printStackTrace();
try {
method.invoke(activity, v);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
}
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OnClickUtils.inject(this);
}
@InjectOnClick({R.id.tvTest, R.id.tvTest2})
private void OnClick(View view) {
int id = view.getId();
if (id == R.id.tvTest) {
} else if (id == R.id.tvTest2) {
}
}
6.结尾
- 注解使用简单,但经常需要配合反射技术,后续有学习更多注解知识,就分享给大家。