Android进阶之手写butterknife-apt简化版

382 阅读2分钟

github.com/JakeWharton… butterknife虽然已经过时(google 推出了databinging),但是其中涉及的一些技术依旧非常经典。主要是注解,apt。 这里安卓进阶,学习注解和apt技术,尝试手写butterknife的简化版。

开发环境:

win10 As4.1 java8 gradle:4.0.1

工程开始:

新建了一个工程,除了app 模块,另外新建了两个java library 和一个android library

先编写注解类,放在java库 libButt中

主要写了两个简单注解BindView 和 OnClick. 这部分简单,不多讲,别处资料很多。

然后是apt 注解处理器部分,包含一个接口IBinder和另一核心注解处理类AnnotationCompiler:

IBinder是个接口,用来绑定,可以看到这边绑定主要传递了一个泛型参数,是什么呢?是Activiy的引用。

libButtAnd 是安卓库,应为此处含有Activity的引用,可以注意这边拿了activity名字,通过反射拿到继承IBinder的类,进行绑定

AnnotationCompiler是非常关键,主要就是查询,处理之前创建的注解,然后编译期间动态生成代码。这就是apt的核心。

关键点在于复写 process方法。 这里面可以拿到注解和注解值,进行代码生成操作。

可以先看下生成之后的代码:

可以看到 类名 Activity类名字加上 _ViewBinding 后缀,和上面反射一致。继承了IBinder接口,泛型传入activity。复写bind方法时候,增加对控件的处理。

这个文件的生成逻辑,就是在 process方法中写的。

看一下调用:

再回过头去看生成的 ButtTestAct_ViewBinding。发现是一一对应的。

所以核心还是在于 process中的生成代码。

具体代码不描述,大家可以看官方代码自行尝试。

这边主要讲一个当时自己遇到的问题,如何调试 process的断点? 这边是java lib里面的,而且是编译期间的。我经过一番搜索尝试最终总结,参考 :juejin.cn/post/693720…

以上主要描述了butterknife使用的注解和apt技术 。

然而在早期apt技术出现之前,butterknife主要使用的是 反射。butterknife使用反射的方式参考: juejin.cn/post/684490…

apt方式比反射方式更好,为什么呢? 因为apt是编译期间生成代码,而反射需要代码执行期间去动态构建,消耗更多内存和执行时间。

为什么现在butterknife已经过时? 因为google 推出的databinding使用更简单,效率更高。butterknife 在使用组件化架构的时候,兼容问题很多。

尝试 databinding ,也可以发现其运用了apt技术,使用时在Build文件夹生成了代码。

over