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. form表单里如果只存在一个文本框,enter键提交

    在这里说一说浏览器里form表单的默认行为 我们都知道浏览器是存在很多默认行为的,可能是出于常用行为考虑又或者是历史原因.但有时候我们不需要这些默认行为.以下: 1).当form表单里只存在一个inp ...

  2. 在xaf 14 中实现 Tonyyang原文中的action权限

    具体实现过程,主要修改了以下几个地方: 第一:角色和用户类中需要修改成SecurityStrategy的方式: 具体代码 MySecurityRole: using System; using Sys ...

  3. 类的序列化和反序列化(ObjectOutputStream和ObjectInputStream)

    1.需要序列化的类 import java.io.Serializable; /** * 必须继承 Serializable 接口才能实现序列化 */ public class Employee im ...

  4. 使用PHP发送email进行账号激活或者密码修改操作

    使用PHPMailer编写发送邮件 PHPMailer需PHP的socket扩展支持,而PHPMailer链接qq域名邮箱时需要ssl加密方式(qq邮箱最近做了限制,新开域名邮箱不再允许通过smtp协 ...

  5. HTML 导航框架 (使用 Frame )

    文章出处  :  http://blog.sina.com.cn/s/blog_6f6d07f80100oqlt.html  (本文转自此博客) 在浏览网页时,我们经常会看到一个导航条,当点击导航条上 ...

  6. perl 引用

    数组的数组 $a = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] 哈希的哈希 my $student_properties_of = { 'zdd' => { 'ag ...

  7. XHTML标签的嵌套规则分析

    在 XHTML 的语言里,我们都知道:ul 标签包含着 li.dl 标签包含着 dt 和 dd——这些固定标签的嵌套规则十分明确.但是,还有许多标签是独立的,它们没有被捆绑在一起,比如 h1.div. ...

  8. SQL 存储过程优化经验

    经现场同事反映,他们用的好好的XML 导出工具最近一直报错,经常报数据库连接超时,查看数据库发现已经有100G 以上有空间了. 但导出数据的存储过程里面每次按时间只导1000多条数据,近理说有时间过滤 ...

  9. Codeforces 738D. Sea Battle 模拟

    D. Sea Battle time limit per test: 1 second memory limit per test :256 megabytes input: standard inp ...

  10. Zabbix(一)--zabbix 2.4.8 安装

    zabbix依赖于LAMP,所以部署前要先保证这个平台. 安装服务端(Server) zabbix官网的rpm包都是按照功能分开一个个,比如: zabbix-server-2.4.7-1.el7.x8 ...