作为一个Android程序员,注解(Annotation)会是一个让我们事半功倍的一个开发利器,它可以简化代码(如ButterKnife),可以约束输入条件(如support-annotations),可以将输入条件改为配置(如Retrofit 2.0)等,就让我们开下注解在注解在Android开发中是怎么使用。

为了容易让大家理解什么是注解,文章会分为分为以下两篇来分别介绍:

  • 注解的基本概念以及自定义注解
  • 定义自己的Annotation Processor
  • 模仿ButterKnife

目标

今天我们的任务是自定义一个注解,并在运行时获取到它的值。

— 代码1:—

1
2
3
4
5
6
public class MainActivity extends AppCompatActivity {
@BindView(R.id.btnTest)
Button btnTest;


}

自定义注解

Java1.5引入了注解,当前许多框架中大量使用注解,如Spring。我们可以自己定义注解来, 这些注解会在编译过程或执行时产生作用。

如上面的代码中@BindView就是一个自定义的注解,我么需要在使用前先声明:

1
2
3
4
5
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}

首先BindView这不是一个接口,因为它的声明是@interface,其次它的定义需要用到RetentionTarget这两个元注解。

元注解

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

  • @Target,
  • @Retention,
  • @Documented,
  • @Inherited

@Target

@Target主要是描述注解的范围,如包,类,变量等,像代码1中的BindView是声明在变量上,下面是target常用的几个:

  1. CONSTRUCTOR:用于描述构造器
  2. FIELD:用于描述域
  3. LOCAL_VARIABLE:用于描述局部变量
  4. METHOD:用于描述方法
  5. PACKAGE:用于描述包
  6. PARAMETER:用于描述参数
  7. TYPE:用于描述类、接口(包括注解类型) 或enum声明

Retention

Retention代表它什么时候发生作用,常用就三种:

  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在class文件中有效(即class保留)
  3. RUNTIME:在运行时有效(即运行时保留)

@Documented

主要是javadoc档案化需要

@Inherited:

@Inherited阐述了某个被标注的类型是被继承的

验证自定义的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void processAnnotation() {
Log.e(TAG, "btn id : " + R.id.btnTest );


Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(BindView.class)) {
BindView bindView = field.getAnnotation(BindView.class);
int viewID = bindView.value();
Log.e(TAG, "processAnnotation: " + viewID );
}
}

}

发现打印的两个值是相等的。