ButterKnife源码解析

简介: ButterKnife(https://github.com/JakeWharton/butterknife)是一款android平台的依赖注入框架,通过该工具可以实现View、OnClickListener的注入,省去了findViewById、setOnClickListener的过程。

ButterKnife(https://github.com/JakeWharton/butterknife)是一款android平台的依赖注入框架,通过该工具可以实现View、OnClickListener的注入,省去了findViewById、setOnClickListener的过程。使用方法如下:

img_f9d4d30aa5818bf36de41fd4da9113f9.png

通过@BindView注解实现findViewById的功能,完成View注入;通过@OnClick完成OnClickListener点击事件的注入,给ID对应的View设置点击事件和响应函数。关于注解的定义和解析可以参照这篇文章:Java注解。ButterKnife使用的就是编译时解析注解的技术,在编译时对注解进行解析,生成中间文件,在ButterKnife.bind时引用注解编译器生成的中间文件,完成依赖注入。

注解的定义

img_cdfda2760245995bb0a43e4741570a5b.png
BindView注解定义

BindView注解定义中使用了元注解@Retention(CLASS)定义了该注解只保留到编译期间,运行时会丢弃;@Target(FIELD)表示该注解只能用在成员变量上面。

img_f1e549f10c8d0394c4ded719943ad19a.png
OnClick注解

OnClick注解中@Target(METHOD)表示该注解只能用于方法上;

img_a1a9d2a00166802f3a7b6ae254faeabe.png
ListenerClass

ListenerClass是一个@Target(ANNOTATION_TYPE)类型的注解,表示ListenerClass只能用在注解上;且@Retention(RUNTIME)表示该注解可以保留到JVM中,也就是运行时能够通过反射来获取。

注解的解析

下面对@BindView和@OnClick两种注解的解析进行讲解。编译时注解的解析:

 编译时 Annotation 指 @Retention 为 CLASS 的 Annotation,由编译器自动解析。需要做的

    a. 自定义类集成自 AbstractProcessor(编译器在编译时自动查找所有继承自 AbstractProcessor 的类,然后调用他们的 process 方法去处理)

    b. 重写其中的 process 函数

ButterKnife实现了ButterKnifeProcessor来进行编译时注解的解析:

img_2fd33b55a3fd046572d2b9d016ff4bb2.png
ButterKnifeProcessor

ButterKnifeProcessor.process()函数如下:

img_d3cc0680a4171336f8fe09f003d23064.png
ButterKnifeProcessor.process

process函数先调用findAndParseTargets生成bindingMap,然后通过binding.brewJava老生成Java文件。findAndParseTargets的实现如下(这里只关注@BindView和@OnClick):

img_4e9678dcb2307208deca71091b20fe32.png
findAndParseTargets

其中调用parseBindView对注解为@BindView的Field进行解析;findAndParseListener对@OnClick之类的Listener注解进行解析。parseBindView代码如下:

img_e6aa543ec32df36ef9ec984e6827bf53.png
parseBindView

parseBindView的主要工作是创建了BindingSet.Builder。getOrCreateBindingBuilder()如下:

img_6759ee75a70c74ecdc7f64d3c3b636e3.png
getOrCreateBindingBuilder

getOrCreateBindingBuilder内部调用了BindingSet.newBuilder。

img_b8a95070f1f82fefb50e5756d830d210.png
BindingSet.newBuilder

newBuilder生成了Builder对象,Builder对象定义了生成的Java文件名、mView所属对象的类型等。Builder对象生产后,parseBindView就根据@BindView注解信息生成FieldViewBinding对象,之后调用了Builder.build()函数;@BindView的解析已经完成后,最后通过BindingSet.brewJava来生成中间文件。@BindView在生成文件对应了如下:

img_f74fd582108c2e1b1707319fa54c2f95.png
addViewBinding

生成的中间文件如下所示:

img_5e8818d56c9737d35b5684ccb72970f5.png
中间文件

可以看到,中间文件里完成了对Target中成员变量的注入。

那么中间文件又是在什么时候被调用的呢?答案就是ButterKnife.bind(this)

img_11cb3dede303ba2de64d025e3a995f45.png

bind函数根据调用的类名查找其对应的className_ViewBinding的类名,然后反射调用其构造函数。

至此,ButterKnife的@BindView的运行流程就是这样。

目录
相关文章
|
8天前
|
移动开发 网络协议 安全
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
64 4
|
9天前
|
域名解析 网络协议 应用服务中间件
2024最新彩虹聚合DNS管理系统源码v1.3 全开源
聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:阿里云、腾讯云、华为云、西部数码、DNSLA、CloudFlare。 本系统支持多用户,每个用户可分配不同的域名解析权限;支持API接口,支持获取域名独立DNS控制面板登录链接,方便各种IDC系统对接。
59 0
|
15天前
|
Linux 网络安全 Windows
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
|
16天前
HuggingFace Tranformers 源码解析(4)
HuggingFace Tranformers 源码解析
81 0
|
16天前
HuggingFace Tranformers 源码解析(3)
HuggingFace Tranformers 源码解析
71 0
|
16天前
|
开发工具 git
HuggingFace Tranformers 源码解析(2)
HuggingFace Tranformers 源码解析
36 0
|
16天前
|
并行计算
HuggingFace Tranformers 源码解析(1)
HuggingFace Tranformers 源码解析
33 0
|
18天前
PandasTA 源码解析(二十三)
PandasTA 源码解析(二十三)
48 0
|
18天前
PandasTA 源码解析(二十二)(3)
PandasTA 源码解析(二十二)
41 0
|
18天前
PandasTA 源码解析(二十二)(2)
PandasTA 源码解析(二十二)
46 2

推荐镜像

更多