Android 编译时注解-提升
背景
在前面的文章中,讲解了注解和编译时注解等一些列相关的内容,为了更加全面和真是的了解Android
编译时注解在实战项目中的使用,本文采取实现主流框架butterknife
注入view
去全面认识编译时注解。
效果
先来张图压压惊,实现效果butterknife
的view
绑定
使用
仿照butterknife
实现了@BindView
注解,通过WzgJector.bind
方法绑定当前MainActivity
,整体和butterknife
使用完全一模一样,这里为了区分简单的把butterknife
改名了WzgJector
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv_msg)
TextView tvMsg;
@BindView(R.id.tv_other)
TextView tvOther;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WzgJector.bind(this);
if(tvMsg!=null){
tvMsg.setText("我已经成功初始化了");
}
if(tvOther!=null){
tvOther.setText("我就来看看而已");
}
}
}
实现
实现的思路和Android
编译时注解-初认识实现原理大致一样,所以这里不重复阐述重复的步骤,重点讲解提升的技术点,所以需要在了解基本编译时注解的前提下继续下面的学习
定义注解
这里使用了java
和android
自带的注解,初始一个BindView
注解,同时指定了@Target
为FIELD
,注解BindView
带有一个初始的int
参数及时使用时的view-id
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}
对java
和android
自带的注解不太清楚的同学可参考下面两篇文章
Element
详解
Element
有了注解,必然需要有一个对应的注解处理器去处理注解,但是在处理注解的时候需要充分的了解注解处理器中的process
方法及时核心的编译代码,而process
方法的核心便是Element
对象,所以在讲解注解处理器前,需要对Element
有全面的认识,方能事半功倍。
由于Element
的知识内容的复杂性,这里重点讲解核心内容,基本使用完全是足够了
源码:
public interface Element extends AnnotatedConstruct {
TypeMirror asType();
ElementKind getKind();
Set<Modifier> getModifiers();
Name getSimpleName();
Element getEnclosingElement();
List<? extends Element> getEnclosedElements();
boolean equals(Object var1);
int hashCode();
List<? extends AnnotationMirror> getAnnotationMirrors();
<A extends Annotation> A getAnnotation(Class<A> var1);
<R, P> R accept(ElementVisitor<R, P> var1, P var2);
}
可看出其实Element
是定义的一个接口,定义了外部调用暴露出的接口
方法 | 解释 |
---|---|
asType | 返回此元素定义的类型 |
getKind | 返回此元素的种类:包、类、接口、方法、字段…,如下枚举值 |
getModifiers | 返回此元素的修饰符,如下枚举值 |
getSimpleName | 返回此元素的简单名称,比如activity名 |
getEnclosingElement | 返回封装此元素的最里层元素,如果此元素的声明在词法上直接封装在另一个元素的声明中,则返回那个封装元素; 如果此元素是顶层类型,则返回它的包如果此元素是一个包,则返回 null; 如果此元素是一个泛型参数,则返回 null. |
getAnnotation | 返回此元素针对指定类型的注解(如果存在这样的注解),否则返回 null。注解可以是继承的,也可以是直接存在于此元素上的 |
getKind
方法
其中getKind
方法比较特殊,getKind()
方法来获取具体的类型,方法返回一个枚举值TypeKind
源码:
public enum TypeKind {
/** The primitive type {@code boolean}. */
BOOLEAN,
/** The primitive type {@code byte}.