一.注解基础
元注解有:
@Retention:注解保留的生命周
@Target:注解对象的作用范围。
@Inherited:Inherited标明所修饰的注解,在所作用的类上,是否可以被继承。
@Documented:如其名,javadoc的工具文档化,一般不关心。
@Retention:
Retention说标明了注解被生命周期,对应RetentionPolicy的枚举,表示注解在何时生效:
SOURCE:只在源码中有效,编译时抛弃,如
@Override
。不加载到虚拟机CLASS:编译class文件时生效。保留在源码中,但是不加载到虚拟机。即编译时注解
RUNTIME:运行时才生效。保留在源码中,也加载到虚拟机。即运行时注解
@Target
Target标明了注解的适用范围,对应ElementType枚举,明确了注解的有效范围。
- TYPE:类、接口、枚举、注解类型。
- FIELD:类成员(构造方法、方法、成员变量)。
- METHOD:方法。
- PARAMETER:参数。
- CONSTRUCTOR:构造器。
- LOCAL_VARIABLE:局部变量。
- ANNOTATION_TYPE:注解。
- PACKAGE:包声明。
- TYPE_PARAMETER:类型参数。
- TYPE_USE:类型使用声明。
@Inherited
注解所作用的类,在继承时默认无法继承父类的注解。除非注解声明了 @Inherited。同时Inherited声明出来的注,只对类有效,对方法/属性无效。
如下方代码,注解类@AInherited
声明了Inherited ,而注解BNotInherited 没有,所在在它们的修饰下:
- 类Child继承了父类Parent的
@AInherited
,不继承@BNotInherited
; - 重写的方法
testOverride()
不继承Parent的任何注解; testNotOverride()
因为没有被重写,所以注解依然生效。
二.源码分析
ButterKnife主要是通过在编译时注解完成得,编译时注解需要生成对应java代码,实现注入。通过ButterKnife注解的类会生成一个结尾为_ViewBinding 的类,如下例子:
// Generated code from Butter Knife. Do not modify!
package com.hangzhou.h890.meihao.account.activity;
import android.support.annotation.CallSuper;
import android.support.annotation.UiThread;
import android.view.View;
import butterknife.Unbinder;
import butterknife.internal.DebouncingOnClickListener;
import butterknife.internal.Utils;
import com.hangzhou.h890.meihao.R;
import java.lang.IllegalStateException;
import java.lang.Override;
public class LoginActivity_ViewBinding<T extends LoginActivity> implements Unbinder {
protected T target;
private View view2131689659;
private View view2131689709;
private View view2131689710;
private View view2131689711;
private View view2131689712;
private View view2131689713;
@UiThread
public LoginActivity_ViewBinding(final T target, View source) {
this.target = target;
View view;
view = Utils.findRequiredView(source, R.id.iv_close, "method 'onViewClicked'");
view2131689659 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
view = Utils.findRequiredView(source, R.id.bt_login, "method 'onViewClicked'");
view2131689709 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
view = Utils.findRequiredView(source, R.id.tv_forget_psw, "method 'onViewClicked'");
view2131689710 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
view = Utils.findRequiredView(source, R.id.tv_register, "method 'onViewClicked'");
view2131689711 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
view = Utils.findRequiredView(source, R.id.iv_weichat_login, "method 'onViewClicked'");
view2131689712 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
view = Utils.findRequiredView(source, R.id.tv_weichat_login, "method 'onViewClicked'");
view2131689713 = view;
view.setOnClickListener(new DebouncingOnClickListener() {
@Override
public void doClick(View p0) {
target.onViewClicked(p0);
}
});
}
@Override
@CallSuper
public void unbind() {
if (this.target == null) throw new IllegalStateException("Bindings already cleared.");
view2131689659.setOnClickListener(null);
view2131689659 = null;
view2131689709.setOnClickListener(null);
view2131689709 = null;
view2131689710.setOnClickListener(null);
view2131689710 = null;
view2131689711.setOnClickListener(null);
view2131689711 = null;
view2131689712.setOnClickListener(null);
view2131689712 = null;
view2131689713.setOnClickListener(null);
view2131689713 = null;
this.target = null;
}
}
这就是ButterKnife的注入类,当我们点击onViewClicked方法可以跳转到原始类。从这个注册类可以看出,在构造中findview找出控件,在unbind中进行置null处理,让告诉gc在合适的机会回收占用的内存 ;
这个注入类是通过核心类注解器ButterKnifeProcessor生产的。
二.核心类ButterKnifeProcessor,继承AbstractProcessor
抽象处理器 AbstractProcessor
我们自定义的处理器需要继承这个抽象处理器。
一般我们会用到它的四个方法。
init(ProcessingEnvironment processingEnvironment)
里面提供了Filer等工具类。注解处理器可以用Filer类创建新文件(源文件、类文件、辅助资源文件)。由此方法创建的源文件和类文件将由管理它们的工具(javac)处理。
getSupportedSourceVersion()
支持JDK的版本,通常返回SourceVersion.latestSupported()。
public Set getSupportedAnnotationTypes()
注解处理器是注册给哪些注解使用的。
public boolean process(annotationsannotations, RoundEnvironment roundEnv)
核心方法,在这里你可以扫描和处理注解,并生成java文件。
待续。。。。