最初的开始,findViewById()获取View控件,setOnClickListener设置View的监听事件,然后UI界面开始有响应。当初完成这个操作,有点兴奋,而这也成为我Android开发的起点。随着时间的推移,android也越来越熟悉,findViewById和setOnClickListener不知写了多少遍,偶发现有好大一部分时间,就是在写findViewById获取变量。针对这问题,在网络上发现了Jake Wharton大神的Butterknife开源框架,后用之,节约了很多时间。本篇博文将会对Butterknife源码进行解析。
一、什么是Butterknife?
Butterknife,是专门为Android View设计的绑定注解框架,专业解放各种findViewById和setOnClickListener。
Butterknife地址:https://github.com/JakeWharton/butterknife
二、Butterknife源码解析
1.Butterknife绑定分析
由1知,@BindView注解FeedbackActivity的3个View变量,由2知,@OnClick注解View的监听事件。然而这三个变量和监听事件,是怎么和FeedbackActivity关联起来的呢?这里就需要我们注意3与Activity的绑定,即ButterKnife.bind(this)方法。进入ButterKnife源码看看。
ButterKnife中bind有多个重载,针对View,Dialog,Activtiy等,具体可以自行查看ButterKnife源码,这里主要针对Activity。我们继续看createBinding方法,
findBindingConstructorForClass()通过传入目标类即Activity,查找辅助绑定类的构造方法。继续看findBindingConstructorForClass()方法
通过反射加载FeedbackActivity_ViewBinding类,而FeedbackActivity_ViewBinding类到底像啥样呢?这里我们可以先看一下此类,后面将会分析此类怎么生成。
其中findRequiredViewAsType和findRequiredView方法皆是Utils的方法,我们查看Utils方法可以知道,两个方法最后都调了findViewById方法,从而就绑定了注解的View变量,绑定View监听事件。
到这里,ButterKnife的绑定流程就介绍完了。ButterKnife主要就是通过注解,然后生成一个辅助类动态绑定View,解放开发者。下面我们将会分析辅助类FeedbackActivity_ViewBinding的生成。
2.Butterknife辅助类的生成
由上,我们知Butterknife框架是用注解的方式实现的,注解的实现方式,很容易让我们想到通过Java反射机制实现,但是我们知道如果通过反射,是在运行时(Runtime)来处理View的绑定等一些列事件,这样比较耗费资源,会影响应用的性能。Butterknife框架没有用java反射机制,而是使用APT(Annotation Processing Tool)编译时解析技术。提到APT,我们就必须要了解AbstractProcessor类,通过继承此类,编译器在编译的时候,会扫描所有带有你注解的类,然后再调用AbstractProcessor的process方法,对注解进行处理,然后生成相关的辅助类,如上FeedbackActivity_ViewBinding。
在Butterknife框架中ButterKnifeProcessor继承了AbstractProcessor,所以我们重点来关注一下ButterKnifeProcessor的process方法
通过遍历bindingMap,再利用JavaFile,就可以生成辅助类了。bindingMap的类型为Map
方法scanForRClasses,主要是扫描所有类,区分注解类。这里不重点讲了。拿到@BindView的注解类后,遍历,然后通过parseBindView方法解析,我们继续看parseBindView方法
第一次,一般都为空值,所以会执行getOrCreateBindingBuilder(builderMap, enclosingElement)方法,其中传入了BuilderMap和enclosingElement,我们继续来看方法getOrCreateBindingBuilder
其中,再次判断了builderMap中是否已存在BindingSet.Builder,不存在就新建,通过BindingSet.newBuilder(enclosingElement)方法,让我继续看BindingSet中newBuilder方法
上面说到BindingSet对辅助类的生成起到非常重要的作用,这里生成了辅助类的类名,并保存在bindingSet.builder中,最后put入了builderMap中。在解析的过程中,BindingSet的都伴随左右,可以看出她在ButterKnifeProcessor类中的重要性。到这里我们在回溯一下。
1.BindingSet.newBuilder(enclosingElement) 生成类名及相关类型定义 -> 2.BuilderMap.put(enclosingElement, builder) put入Map
到这里,Butterknife框架生成辅助类,就讲解的差不多了。其中核心原理就是利用BindingSet类强大的类构建能力,生成相关类名,方法和核心代码。对于BindingSet具体是怎么生成辅助类的,想深入了解的朋友也可以下载ButterKnife源码对BindingSet进行深度了解,这里主要介绍ButterKnife框架原理。
三、总结
通过了解Butterknife框架,知其思想真是值得称赞。注解绑定一下,就告别重复的findViewById等方法,节约了开发时间,提高了效率。