ButterKnife的原理简述

注解处理器
Java5 中叫APT(Annotation Processing Tool),在Java6开始,规范化为 Pluggable Annotation Processing。

第一步(收集信息)

找到所有被注解的属性或者方法,将所有的信息收集到对应的“类数据集”中。

第二步(生成源文件)

根据每一个“类数据集”,生成对应的java源文件。由于这些文件并不是在运行时生成的,因此也无需动态编译,注解处理器运行完成之后,
编译器会处理所有的编译流程。

第三步(动态注入)

运行时动态注入,即用户常规调用的 ButterKnife.bind(activity)

这一步为了避免蹩脚的调用,使用了运行时反射,但是作者对每一个类进行了缓存,因此,不会对执行效率产生多大影响。

在最新的 ButterKnife 源码(2015.06.08)中,ButterKnife已经重构了部分方法:

ButterKnife#inject -> ButterKnife#bind

@InjectView -> @FindView

等等,具体变化可以去看官方文档,**本文档后续代码使用最新版本代码演示**。

极简实现演示

演示代码说明

示例代码由 ButterKnife 简化而来,部分定义和实现有删改,只能绑定 Activity 中的 View 字段 为了避免引入Android平台,但是又需要更直观,所以mock了android的两个类,Activity 和 View 为了避免使用 Pluggable Annotation Processing 过程中的jar包要求,以及波及不必要的java文件,请使用命令行运行演示,直接运行 ./run.sh 即可查看结果 保证 CLASSPATH 中含有tools.jar

第一步(收集信息)

在每一个类中找到所有被 FindView 注解的字段

每一个需要绑定的字段信息都保存为一个 FieldViewBinding 对象,比如:

@FindView(100)
View vView1;
得到:
new FieldViewBinding(vView1, android.view.View, 100)

将字段分类,获取每一个类的“类数据集”BindingClass,比如, MainActivity 对应的 “类数据集” 如下:

MainActivity:
    List<FieldViewBinding> fieldViewBindings = new ArrayList<FieldViewBinding>();
    fieldViewBindings.add(new FieldViewBinding(vView1, android.view.View, 100))
    fieldViewBindings.add(new FieldViewBinding(vView2, android.view.View, 200))

第二步(生成 Bind 工具类源文件)

为了便于在反射时容易实例化生成的类,每一个生成的类都实现了一个 ActivityBinder 接口,因此,根据 MainActivity “类数据集”生成的文件如下:

package sample;

import android.view.View;
import android.app.Activity;
import butterknife.ButterKnife.ActivityBinder;

public class MainActivity$$ViewBinder implements ActivityBinder<sample.MainActivity> {
    @Override
    public void bind(sample.MainActivity target) {
        View view;
        view = target.findViewById(100);
        target.vView1 = view; //这里要求 vView1 的访问权限为 package 级别
        view = target.findViewById(200);
        target.vView2 = view;
    }
}

第三步(动态注入)

我们在 MainActivity 中调用 ButterKnife#bind,第一件事就是找到对应生成的 Bind 工具类,这里遵循命名规则(在对应类后增加 $$ViewBinder 后缀),直接使用动态加载并实例化:

Class<?> activityBindingClass = Class.forName(targetClass.getName() + ButterKnifeProcessor.SUFFIX);
activityBinder = (ActivityBinder) activityBindingClass.newInstance();

获得相应的 ActivityBinder 之后,使用 ActivityBinder#bind 进行绑定,与手动调用 findViewById 效果相同

运行

运行:

ButterKnifeProcedure/src$ ./run.sh

结果:

mainActivity.vView1.id = 100
mainActivity.vView2.id = 200
时间: 2024-08-25 23:02:27

ButterKnife的原理简述的相关文章

【Android】ButterKnife 简单原理实现

ButterKnifeProcedure ButterKnife的原理简述 示例代码ButterKnifeProcedure Pluggable Annotation Processing 注解处理器Java5 中叫APT(Annotation Processing Tool),在Java6开始,规范化为 Pluggable Annotation Processing. 第一步(收集信息) 找到所有被注解的属性或者方法,将所有的信息收集到对应的"类数据集"中. 第二步(生成源文件) 根

TCP/IP协议工作原理简述

TCP/IP协议工作原理简述 Table of Contents 1 概要 2 应用层 3 传输层 4 网络层 5 链路层 1 概要 协议是什么?协议是一组为完成特定需求或功能而定义的标准通讯格式.协议是服务于具体需求或功能的,它不能独立存在. 制定TCP/IP协议的目的是为了解决主机互联以及互联的主机上的应用通讯的问题.TCP/IP协议共有四层:应用层.传输层.网络层.链路层.应用层实际就是我们的应用程序,对于非具体应用而言这一层的协议是未定义的,需要我们自己根据我们具体的业务模型来制定.传输

Android butterknife 实现原理

简介 ButterKnife 是一个 Android 系统的 View 注入框架,能够通过『注解』的方式来绑定 View 的属性或方法. 比如使用它能够减少 findViewById() 的书写,使代码更为简洁明了,同时不消耗额外的性能. 当然这样也有个缺点,就是可读性会差一些,好在 ButterKnife 比较简单,学习难度也不大. 添加依赖 这里以 Android Studio Gradle 为例,为项目添加 ButterKnife,注意两个步骤都要完成: 1. Project 的 buil

Android-ButterKnife不能注解RatingBar(含ButterKnife部分原理以及View传递机制)

继续把之前的安卓外包的一些东西写出来. 文章结构:(1)RatingBar基本使用(自定义样式):(2)ButterKnife不能注解RatingBar以及在项目解决的方式:(3)ButterKnife原理以及View机制原理 一.RatingBar基本使用(自定义样式): (1)一个style样式: <style name="roomRatingBar" parent="@android:style/Widget.RatingBar"> <ite

Butterknife实现原理

Butterknife实现原理 一.简介 1.特点 低版本不使用APT(Annotation Processing Tool)编译时解析技术,使用时仅添加依赖.在Butterknife8.0版本及以上使用APT. 一般注入框架都是运行时注解,即声明注解的生命周期为RUNTIME,然后在运行的时候通过反射完成注入,方式虽然简单,但会有 性能的损耗.我们不用再重复写findViewById和onClick,框架在编译的时候帮我们自动生成了这些代码,在运行时调用. 二.源码分析 2.1 步骤 1)在o

java多线程模式ThreadLocal原理简述及其使用详解

原创整理不易,转载请注明出处:java多线程模式ThreadLocal原理简述及其使用详解 代码下载地址:http://www.zuidaima.com/share/1781557457128448.htm ThreadLocal是为了使每个线程保存一份属于自己的数据. 先看一个使用ThreadLocal的实例. package com.zuidaima.aop.framework; import com.zuidaima.core.NamedThreadLocal; public abstra

Volley实现原理简述

Volley实现原理简述 一.介绍 Volley是Goole退出的Android异步网络请求框架和图片加载框架. 主要特点: 1)扩展性强.Volley大多是基于接口的设计. 2)符合Http规范. 3)Android2.3及以上版本默认基于HttpUrlConnection,2.3以下基于HttpClient. 4)提供简便的图片加载工具. 二.使用 1.调用:通过newRequestQueue()函数新建并启动一个请求队列,向RequestQueuezhon 不断add Request. 代

Gexmul虚拟机内存空间原理简述

Gxemul将内存空间分为两部分管理,一部分是物理内存,地址分配到0x00000000,另一部分是device的地址,注册device的时候由device自己指定空间 1 创建物理内存 memory.cc memory_new {     初始化物理内存参数     mem->physical_max = physical_max;     mem->dev_dyntrans_alignment = 4095;     创建物理内存     mem->pagetable = (unsig

FileCloud 的原理简述&amp;自己搭建文件云

FileCloud 的原理简述&自己搭建文件云 copyright(c) by zcy 关于如何使用IIS创建asp服务,请读者自行研究 代码的存储: 根目录 filecloudEV.html 提前验证 filecloudEV.aspx 判断密码是否正确 filecloudMAIN.aspx 主界面 UpLoad.asp 上传界面 SaveFile.asp 保存文件 InputFilename.aspx 让用户输入文件名 AddPath.aspx 将当前文件加入文件清单 clsField.asp