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

ButterKnife的原理简述的更多相关文章

  1. TCP/IP协议工作原理简述

    TCP/IP协议工作原理简述 // */ // ]]>   TCP/IP协议工作原理简述 Table of Contents 1 概要 2 应用层 3 传输层 4 网络层 5 链路层 1 概要 ...

  2. Excel阅读模式/聚光灯开发技术序列作品之三 高级自定义任务窗格开发原理简述—— 隐鹤

    Excel阅读模式/聚光灯开发技术序列作品之三 高级自定义任务窗格开发原理简述——    隐鹤 1. 引言 Excel任务窗格是一个可以用来存放各种常用命令的侧边窗口(准确的说是一个可以停靠在类名为x ...

  3. Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述—— 隐鹤 / HelloWorld

    Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述———— 隐鹤  /  HelloWorld 1. 引言 自本人第一篇博文“Excel阅读模式/单元格行列指示/聚光灯开发技术要 ...

  4. FileCloud 的原理简述&自己搭建文件云

    FileCloud 的原理简述&自己搭建文件云 copyright(c) by zcy 关于如何使用IIS创建asp服务,请读者自行研究 注:不要忘记添加入站规则 代码的存储: 根目录 fil ...

  5. 网络知识杂谈 - https - 原理简述

    概述 简单描述 https 尽量介绍它的原理 实际的机制, 可能会更加复杂一些... 背景 这玩意, 困扰我好多年了 今天开始, 想做个了断 之前工作也接触过, 但从我的角度来说, 认识很浅 会配置 ...

  6. UPS不间断电源工作原理简述

    原文地址:https://blog.csdn.net/uamix/article/details/52776297 一.定义 UPS即不间断电源,是将蓄电池(多为铅酸免维护蓄电池)与主机相连接,通过主 ...

  7. SeqGAN 原理简述

    1. 背景GAN在之前发的文章里已经说过了,虽然现在GAN的变种越来越多,用途广泛,但是它们的对抗思想都是没有变化的.简单来说,就是在生成的过程中加入一个可以鉴别真实数据和生成数据的鉴别器,使生成器G ...

  8. frame shiro 认证示例及原理简述

    shiro 认证流程 1.创建一个 javaSE 的maven项目(quickstart),并添加依赖 <dependency> <groupId>junit</grou ...

  9. linux文件系统实现原理简述【转】

    本文转载自:https://blog.csdn.net/eleven_xiy/article/details/71249365 [摘要] [背景] [正文] [总结]   注意:请使用谷歌浏览器阅读( ...

随机推荐

  1. shell编程之运算符

    declare声明变量类型 declare    [+ / -] [选项]  变量名 - :给变量设定类型属性 + :取消变量的类型属性 -a :将变量声明为数组型 -i :将变量声明为整数型 -x ...

  2. JDBC 工具类

    在Java编程过程中 我们需要连接数据库 所以数据库的连接和增删改查操作是非常基本的操作同时又非常的重要.同时在JDBC编程中 ,有很多的方法如更新个查找操作,我们可以对其进行封装,提高我们编码的效率 ...

  3. 浅谈Oracle表之间各种连接

    Oracle表之间的连接分为三种: 1.内连接(自然连接) 2.外连接 2.1.左外连接(左边的表不加限制,查询出全部满足条件的结果) 2.2.右外连接(右边的表不加限制,查询出全部满足条件的结果) ...

  4. UILabel顶端对齐

    比较一劳永逸的写法是对label添加一个分类 @interface UILabel (VerticalAlign) /** 顶端对齐 */ -(void)alignTop; /** 底部对齐 */ - ...

  5. Miller_Rabin素数测试

    #include<iostream> #include<cmath> #include<cstdio> #include<cstring> #inclu ...

  6. 现在还需要测试或者QA人员吗?

    Facebook没有专门的测试人员,都是开发自己测:微软裁掉了测试部门,改由开发测:google有少量的测试人员,主要做测试自动化框架开发或者性能.安全等专项测试,测试用例还是开发人员自己设计自己跑( ...

  7. new与malloc

    首先将new与malloc的区别总结如下: 1 new可以自动计算需要分配多大的内存,而malloc必须指明. 2 new返回的指针是有类型的,malloc返回void*类型的指针. 3 new在分配 ...

  8. JSP目录

    JSP目录   课时1    jsp概述和背后原理31:11 课时2    三种jsp的scriptlet语法27:29 课时3    jsp的注释14:00 课时4    JSP4个域对象的作用域3 ...

  9. Java 基本数据类型(新手必看资料)

    变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据. 因此,通过定义不同类型的变量,可以在内存 ...

  10. 操作系统win2003 x64的,安装OFFICE2003后,DCOM服务找不到 WORD应用程序服务

    打开注册表,找到以下健值 HKEY_CLASSES_ROOT\AppID\{00020906-0000-0000-C000-000000000046} HKEY_CLASSES_ROOT\CLSID\ ...