简书排版
http://www.jianshu.com/p/27dab01b29aa
目录
1.简介
注解是JDK 1.5之后引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
2.元注解
Java目前只内置了三种标准注解,以及四种元注解。
@Target:
表示注解该用于什么地方。可能的ElementType参数包括:
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE: 包声明
PARAMETER:参数声明
TYPE:类,接口(包括注解类型)或enum声明
@Retention:
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
SOURCE:注解将被编译器丢弃。
CLASS:注解在class文件中可用,但会被VM丢弃。
RUNTIME:VM将在运行期也保留注解,因此可通过反射机制读取注解的信息。
@Documented:
将此注解包含在Javadoc中
@Inherited:
允许子类继承父类中的注解。
上述内容引自《Java编程思想第四版》
3.一个例子
上述的概念,看着看着就要睡着的感觉,下面列举一个Android中绑定点击事件的例子。
编写注解类BindView.java
//运行时
@Retention(RetentionPolicy.RUNTIME)
//字段
@Target(ElementType.FIELD)
public @interface BindView {
int value() default 0;
boolean onClick() default false;
boolean onLongClick() default false;
}
上述的default表示默认值
再来看看操作类
public class InjectUtils {
//初始化注解
public static void init(Activity ctx) {
try {
Class<?> clazz = ctx.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(BindView.class)) {
BindView inject = field.getAnnotation(BindView.class);
int id = inject.value();
if (id > 0) {
boolean access = field.isAccessible();
field.setAccessible(true);
View child = ctx.findViewById(id);
if (child != null) {
if (inject.onClick() && ctx instanceof View.OnClickListener) {
child.setOnClickListener((View.OnClickListener) ctx);
}
if (inject.onLongClick() && ctx instanceof View.OnLongClickListener) {
child.setOnLongClickListener((View.OnLongClickListener) ctx);
}
}
field.set(ctx, child);
field.setAccessible(access);
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
当然了我这里只写了一个参数类型为Activity的方法
通过反射的方式,通过getAnnotation方法取出标记了注解的字段的value
然后通过上下文findViewById找到相应的控件,设置好对应的点击事件,
这里默认是有传进来的Activity来实现OnClickListener这个接口。
在我们的主Activity中使用
public class MainActivity extends Activity implements View.OnClickListener{
@BindView(value = R.id.btn_bind,onClick = true)
private Button mBtnBind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.init(this);
}
@Override
public void onClick(View v) {
Toast.makeText(this,"BindView Success ...",Toast.LENGTH_SHORT).show();
}
}
如图
响应成功
当然了,注解的强大之处远不及如此,上述仅仅只是一个非常简单的例子,了解一下其中的原理。