背景:
之前使用过butterknife,后来又有了比较热门的Aroute用于项目解耦。两者在代码编译期的实现原理都是差不多的:即使用注解BindView或者Route,如下图:public class MainActivity extends AppCompatActivity {
@BindView(R.id.testId)
TextView mTestId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
在编译之后在/app/build/generated/source/apt/debug/{package}/会生成一个名为MainActivity_ViewBinding的文件:
public class MainActivity_ViewBinding implements Unbinder {
private MainActivity target;
@UiThread
public MainActivity_ViewBinding(MainActivity target) {
this(target, target.getWindow().getDecorView());
}
@UiThread
public MainActivity_ViewBinding(MainActivity target, View source) {
this.target = target;
target.mTestId = Utils.findRequiredViewAsType(source, R.id.testId, "field 'mTestId'", TextView.class);
}
@Override
@CallSuper
public void unbind() {
MainActivity target = this.target;
if (target == null) throw new IllegalStateException("Bindings already cleared.");
this.target = null;
target.mTestId = null;
}
}
PS:至于这个文件是什么时候使用,这个通过ButterKinfe.binder()方法中调用findBindingConstructorForClass()中的一句话Class<?>
bindingClass = cls.getClassLoader().loadClass(clsName +
“_ViewBinding”);使用的。
这部分很简单,看源码跟下去就知道了(反射)
这是怎么做到的呢?想知道这个文件是怎么生成的,何时生成的,请看下面。
原理探究
回顾依赖butterknife时,添加了这么一句话:
annotationProcessor ‘com.jakewharton:butterknife-compiler:9.0.0-rc2’
百度下annotationProcessor,他会在编译期,扫描代码中的注解,根据声明规则,将这些注解交给AnnotationProcessor来处理。
那如何找到这个注解器呢。添加了这个依赖,那么就要去仓库中去下载这个jar包,那我们可以这里入手。
我们可以在用户目录的./.gradle/caches/transforms-1/files-1.1/中找到这个文件:butterknife-compiler-9.0.0-rc2.jar,使用jd_gui打开之后如下:
其中ButterKnifeProcessor就是ButterKnife的注解解析器,其中的process()函数是关键,这个就相当于java应用的main()方法。在这里可以对注解BinderView进行解析,从而生成MainActivity_ViewBinding文件。具体的实现方式太复杂了,这个主要看自己的业务需要。
PS:如何找到butterknife-compiler-9.0.0-rc2.jar这个jar文件呢。我的方法是去用户目录下的.gradle/caches文件下直接搜索这个文件
现在已经知道了Butterknife在编译期生成java是通过annotationProcessor来实现的。那我们自己如何实现一个annotationProcessor呢。这个将在下一篇介绍。