之前有介绍过IOC实现布局、控件、事件的运行时注解。里面使用了大量的反射,难免会影响性能。显而易见,我们常用的butterKnife并没有使用这种技术,而是使用了APT技术,编译时完成这些操作,这样和原始性能相差无几,不过这样会增加apk的体积。下面将学习它的实现原理。
一、使用
1、gradle配置
加入以下依赖
// 依赖库
implementation 'com.jakewharton:butterknife:9.0.0-rc1'
// 注解处理器
annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
2、绑定
调用如下代码
ButterKnife.bind(this);
此时编译一下项目,就会在build编译目录下多出来这样一个文件,截图如下:
没错这就是apt生成的文件。那么它是如何生成的呢?
二、原理
首先进入bind()方法。跟踪进入如下代码:
这里有两个地方需要注意:
- 找到当前绑定类的构造方法
- 构造类对象
首先查看这两个方法具体做了些什么?
1、findBindingConstructorForClass
注意代码中通过 cls.getClassLoader().loadClass 加载 APT 生成的类,也就是之前我们在build目录下看到的那个类。然后拿到它的构造方法。
2、constructor.newInstance
通过分析,通过findBindingConstructorForClass()方法,返回的是APT生成文件的构造器,调用constructor.newInstance()方法,就会实例化该类对象,所以进入该生成类的构造方法。
这里的 tartget 就是我们自己的 activity。使用target.btn1 就可以访问类的属性。所以控件的修饰符不能为private或static。那么它是如何找到view的呢?如何设置事件呢?进入方法findRequiredViewAsType()
3、findRequiredViewAsType (找到view)
ok,看到这里就明白了,还是通过findViewById()来初始化控件。
4、view.setOnClickListener(设置监听)
值得注意的是这里的监听并不是View.OnClickListener。而是它的实现类 DebouncingOnClickListener,代码如下:
它是一个抽象类,最终调用 onClick() 方法的时候,就会触发 doClick() 方法回调。交给 target.clickEvent()进行处理。