Android 注解框架 Butterknife的核心代码分析笔记
Posted zhangjiaofa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 注解框架 Butterknife的核心代码分析笔记相关的知识,希望对你有一定的参考价值。
ButterKnife是一个注解框架,主要是针对android平台。
逐个的来看一下Library中的代码的组织架构:
1、接口Binding 这个接口里面有一定对外的定义的方法,主要的功能就是具有可读性的注解的描述语。
2、ButterKnifeProcessor,这是一个实体类,也是ButterKnife注解框架的核心类。
2、1 首先他集成了JAVA处理注解所用到的抽象类 AbstractProcessor
关于AbstractProcessor的主要功能的说明,做下面的截图的总结:
看一下ButterKnifeProcessor的基本常量有哪些:
public static final String SUFFIX = "$$ViewInjector";
public static final String ANDROID_PREFIX = "android.";
public static final String JAVA_PREFIX = "java.";
static final String VIEW_TYPE = "android.view.View";
private static final String LIST_TYPE = List.class.getCanonicalName();
private static final List<Class<? extends Annotation>> LISTENERS = Arrays.asList(//
OnCheckedChanged.class, //
OnClick.class, //
OnEditorAction.class, //
OnFocusChange.class, //
OnItemClick.class, //
OnItemLongClick.class, //
OnItemSelected.class, //
OnLongClick.class, //
OnPageChange.class, //
OnTextChanged.class, //
OnTouch.class //
);
基本可看出 是一些字符串的常量定于约束 以及观察者方法注解的class集合
再看一下ButterKnifeProcessor的基本变量有哪些:
private Elements elementUtils;
private Types typeUtils;
private Filer filer;
这三个变量应该是对于有些人来说有些陌生,没关系,API是最好的老师:
对于Elements的基本文本描述的定义如下:
用来对程序元素进行操作的实用工具方法。
兼容性注意事项: 在将来的平台版本中可能会向此接口添加一些方法。
主要功能的截图如下:
对于Type的基本文本描述的定义是:
首先明确一点的是Type是一个接口,目前已知实现这个接口的是Class。
Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
对于Filter的文本描述的定义:
此接口支持通过注释处理器创建新文件。以这种方式创建的文件对于实现此接口的注释处理工具将是已知的,这比启用工具来管理它们更好。在对用来编写文件内容的Writer
或 OutputStream
调用 close
方法之后,以这种方式创建的源文件和类文件被认为将由管理它们的工具处理。有三类文件要加以区分:源文件、类文件和辅助资源文件。
基本的功能的截图如下:
3、CollectionBinding 实现了Binding的接口,顾名思义是集合的绑定的定义,其中集合,内部定义了一个枚举类,分别指向的是ARRAY与LIST
4、DebouncingOnClickListener 就是针对Android中的一般性的View多次点击,多次相应而临时处理的抽象类
5、Parameter 这个类是final类型,故是不允许对其进行继承的,
其含义的文本的描述如下:
体现了一个参数的类型一个在观察者的方法内部的位置
6、ListenerBinding 这是一个观察者的绑定,依旧实现了Binding的接口,主要要注意的就是其内部的成员变量中有一个参数的集合的列表。
7、ListenerClass 这是一个定义的注解,其修饰的类型是:
@Retention(RUNTIME) @Target(ANNOTATION_TYPE)
运行时,在class文件中可以通过反射找到,并且类型是注解,可以修饰注解
这个类的内部的定义如下:
String targetType();
/** Name of the setter method on the @link #targetType() target type for the listener. */
String setter();
/** Fully-qualified class name of the listener type. */
String type();
/** Enum which declares the listener callback methods. Mutually exclusive to @link #method(). */
Class<? extends Enum<?>> callbacks() default NONE.class;
/**
* Method data for single-method listener callbacks. Mutually exclusive with @link #callbacks()
* and an error to specify more than one value.
*/
ListenerMethod[] method() default ;
/** Default value for @link #callbacks(). */
enum NONE
这个观察者的set名称 这个观察者的类型的全称 声明观察者回调的枚举 对于单个观察者的回调的方法数据 方法回调的默认的数据
8、ListenerMethod 这依旧是一个定义的注解,
修饰的类型如下:
@Retention(RUNTIME) @Target(FIELD)
这也就是说,运行时可以通过反射获取,还有这个注解是修饰成员变量的
这个注解所在的观察者的方法的应用的名称 方法的参数的集合 观察者的方法回调返回的数据的类型
9、ViewBinding 顾名思义,Android中View的绑定 同样实现了Binding的接口
10、ViewInjection 这个类整体的描述了被注入注解的View
其中维护的成员变量大概包括了id编号、ViewBinding的集合、ListenerBinding的队列集合
11、ViewInjector 给View注入注解的主动者
先看它的成员变量:
private final Map<Integer, ViewInjection> viewIdMap = new LinkedHashMap<Integer, ViewInjection>();
private final Map<CollectionBinding, int[]> collectionBindings =
new LinkedHashMap<CollectionBinding, int[]>();
private final String classPackage;
private final String className;
private final String targetClass;
private String parentInjector;
从其成员变量大致可以进行下面的归纳:
1、维护了注解Vide的ID的队列Map
2、维护了集合绑定的队列Map
3、类的包名
4、类的名称
5、目标类
6、注入的父对象
从其功能函数来看,主要可以进行下面的归纳:
1、添加View的绑定
2、添加观察者的绑定
3、添加集合的绑定
4、设置父节点注入对象
5、动态生成注解的Java文件
12、Bind 这是一个注解,
修饰类型如下:
@Retention(CLASS) @Target(FIELD)
注解会在class文件中存在,但运行时无法获取,同时修饰成员变量的类型
英文注释:Bind a field to the view for the specified ID. The view will automatically be cast to the field
绑定一个成员变量到指定的ID的View上面去,同时这个View会自动的转换成为这个成员变量的类型
内部维护了一个成员变量所绑定的ID的编号
13、BindArray BindBitmap BindBool BindColor BindDimen BindDrawable BindInt BindString
上述的注解都是隶属于同一种规则,也就是绑定一个成员变量到指定ID的类型变量上去
14、ButterKnife
来看一下这个类的注释说明:
Field and method binding for Android views. Use this class to simplify finding views and
attaching listeners by binding them with annotations.
针对的是Android View的变量与方法的绑定。使用这个类来简化找到对应的View以及附加观察者通过将注解与它们绑定的方式。
14、1 Finder 这个是ButterKnife内部定义的一个枚举类
看一下他的注释:
DO NOT USE: Exposed for generated code.
不要直接使用它,这个是暴露给自动生成的代码
同时可以发现,在每一个枚举的常量内部,定义了一些内部的方法:
基本上是对于 类型是View、Dialog、Activity内部如何获取View以及获取Context变量的定义
14、2 接下来看一下几种绑定的方法:
无非就是如何绑定View、Dialog、Activity
15、ImmutableList 这个类定义的是一个不可改变的集合,比一般的集合要轻量级一些。内部是用一个数组来模拟的
16、InjectView InjectViews 对应的是 绑定成员变量到一个View 上面去 一个是单个的int 一个是int[]
17、接下来的一组又是可以进行归类的注解:
OnCheckedChanged
OnClick
OnEditorAction
OnFocusChange
OnItemClick
OnItemLongClick
OnItemSelected
OnLongClick
OnPageChange
OnTextChanged
OnTouch
之所以说上面是可以进行归类的,是因为,它们的注解修饰是一样的:
除了系统级别的
@Target(METHOD)
@Retention(CLASS)
还有两个我们在前面自定义的注解的修饰:
@ListenerClass
@ListenerMethod
在注解ListenerClass 我们可以看到基本类似如下的定义:
targetType = "android.view.View",
setter = "setOnTouchListener",
type = "android.view.View.OnTouchListener",
method = @ListenerMethod(
name = "onTouch",
parameters =
"android.view.View",
"android.view.MotionEvent"
,
returnType = "boolean",
defaultReturn = "false"
)
对上面的代码做如下的大致的解释:
1、当前的观察者的注解所绑定的类的类型
2、设置观察者的set方法的名称
3、当前的观察者的类型
4、它的成员变量method也是一个注解, 包括响应的方法的名称,响应的方法的参数,
响应的方法的函数的回调的类型,响应的方法的函数的回调的默认数值
以上是关于Android 注解框架 Butterknife的核心代码分析笔记的主要内容,如果未能解决你的问题,请参考以下文章
Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架