首页 > 代码库 > Butterknife实现原理
Butterknife实现原理
Butterknife实现原理
一、简介
1、特点
低版本不使用APT(Annotation Processing Tool)编译时解析技术,使用时仅添加依赖。在Butterknife8.0版本及以上使用APT。
一般注入框架都是运行时注解,即声明注解的生命周期为RUNTIME,然后在运行的时候通过反射完成注入,方式虽然简单,但会有
性能的损耗。我们不用再重复写findViewById和onClick,框架在编译的时候帮我们自动生成了这些代码,在运行时调用。
二、源码分析
2.1 步骤
1)在onCreate()中写 ButterKnife.bind(this);和ButterKnife.setDebug(true);bind方法主要是拿到我们绑定的Activity的Class,
然后找到这个Class的ViewBinder,最后调用ViewBinder的bind()方法。
2)打开findViewBinderForClass()先保存了Class为key,Class$$ViewBinder为Value的一个LinkedHashMap,主要是做缓存,提高
下次再来bind的性能。
3)clsName 是我们要传入绑定的Activity类名,相当于拿到了Activity$$ViewBinder。它是Activity的一个内部类,即AbstractProcessor
编译时生成的类。用反射反射了一个viewBinder 实例。此方法中用linkhashMap做了缓存,把刚刚反射的viewBinder作为value,Class作为
key加到LinkedHashMap,下次再bind此类时,直接取出来用,提升性能。
4)返回刚刚的bind方法,我们拿到了这个Activity的viewBinder,然后调用它的bind方法。
2.2 以TextView测试的例子
准备好布局,写上id,ButterKnife的bind()
使用jd-jui等源码查看工具查看所写项目的workspace;路径为
项目名/app/build/intermediates/classes/debug/主Activity所在的包名下MainActivity$$ViewBinder此class文件
实现原理
1)在bind方法中,最后调用了ViewBinder的bind方法,参数:paramFinder是一个Finder,在Activity、Fragment和Adapter等
不同地方都可用butterknife。paramT和paramObject都是我们要绑定的Activity类。
2)返回上面的ViewBinder代码,先调用Finder的findRequiredView(),经过处理就是调用了findView方法,拿到相应的view,
然后再赋值给paramT.textView,paramT就是那个要绑定的Activity。
3)通过 paramT.textView 调用,说明了Activity中不能把TextView设置为private,不然会报错。可以用反射来拿到textView的。
4)最后setOnClickListener,DebouncingOnClickListener这个Listener其实也是实现了View.OnClickListener 方法,然后在
OnClick里面调用了doClick方法。
* Butterknife到底是怎样在编译的时候生成代码的? 我们来看一下它的ButterKnifeProcessor类:
Init方法: ProcessingEnviroment参数提供很多有用的工具类Elements, Types和Filer。
Types是用来处理TypeMirror的工具类。
Filer用来创建生成辅助文件。
ElementUtils是ButterKnifeProcessor运行时,会扫描所有的Java源文件,然后每一个Java源文件的每一个部分都是一个Element,
比如一个包、类或者方法。
getSupportedAnnotationTypes()方法主要是指定ButterknifeProcessor是注册给哪些注解的。把Class文件加到那个
LinkedHashSet里面,然后再把LISTENERS也全部加进去。
其实整个类最重要的是process方法:作用主要是扫描、评估和处理我们程序中的注解,然后生成Java文件。也就是前面说的ViewBinder。
首先一进这个函数就调用了findAndParseTargets方法。其后的方法使用RXJava。
Butterknife实现原理