1.ButterKnife是使用APT(AnnotationProcessor注解处理器,Javac的工具)进行注解,不是使用运行时注解,所以性能没有影响,但对编译器有点时间成本的影响
2.注解分为
普通注解 @Override等
元注解 注解其它注解的注解
1.@Document 应该被Java记录
2.@Target 注解的使用范围
3.@Retention 描述注解的生命周期
4.@inherited 表明注解可继承
3.自定义注解
@Documented
@Target(ElementType.TYPE)//ElementType.TYPE表示用来描述类或者接口(ElementType是枚举类)
@Retention(RetentionPolicy.RUNTIME)//RetentionPolicy.RUNTIME表明 运行时有效(RetentionPolicy是枚举类,也有英文注释)
@Inherited
public @interface metaTest {
// @interface 表明自定义注解
public String doTest();
}
看下ElementType
public enum ElementType {
//有英文注释
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
看下@BindView源码
@BindView(R.id.tv_info)
TextView tv_info;
@Retention(RUNTIME) //注释将由编译器记录在类文件中,并且在运行时由VM保留,因此可以反射地读取它们
@Target(FIELD) //字段声明(包括枚举常量)
public @interface BindView {
/** View ID to which the field will be bound. */
@IdRes int value();
}
注解处理器APT,每一个注解处理器都是继承于AbstractProcessor(注解处理器不能改变Java类)
看下AbstractProcessor这个类
package javax.annotation.processing;
public abstract class AbstractProcessor implements Processor {
//四个核心方法(整个注解处理器是运行在自己的Java虚拟上的)
protected ProcessingEnvironment processingEnv;
private boolean initialized = false;
protected AbstractProcessor() {
//AbstractProcessor 构造函数是空的,它的初始化在init()方法中
}
.
.
.
public synchronized void init(ProcessingEnvironment var1) {
if (this.initialized) {
throw new IllegalStateException("Cannot call init more than once.");
} else {
Objects.requireNonNull(var1, "Tool provided null ProcessingEnvironment");
this.processingEnv = var1;
this.initialized = true;
}
}
public abstract boolean process(Set<? extends TypeElement> var1, RoundEnvironment var2);//最重要的抽象方法,重要程度相当于Main函数,最后会生成Java代码
.
public Set<String> getSupportedAnnotationTypes() {
//返回支持的注解的类型
SupportedAnnotationTypes var1 = (SupportedAnnotationTypes)this.getClass().getAnnotation(SupportedAnnotationTypes.class);
if (var1 == null) {
if (this.isInitialized()) {
this.processingEnv.getMessager().printMessage(Kind.WARNING, "No SupportedAnnotationTypes annotation found on " + this.getClass().getName() + ", returning an empty set.");
}
return Collections.emptySet();//通过集合来判断
} else {
return arrayToSet(var1.value());
}
}
public SourceVersion getSupportedSourceVersion() {
//用来指定所支持的Java版本
SupportedSourceVersion var1 = (SupportedSourceVersion)this.getClass().getAnnotation(SupportedSourceVersion.class);
SourceVersion var2 = null;
if (var1 == null) {
var2 = SourceVersion.RELEASE_6;
if (this.isInitialized()) {
this.processingEnv.getMessager().printMessage(Kind.WARNING, "No SupportedSourceVersion annotation found on " + this.getClass().getName() + ", returning " + var2 + ".");
}
} else {
var2 = var1.value();
}
return var2;
}