【Android】如何实现ButterKnife
如何实现ButterKnife
ButterKnife的原理简述
Pluggable Annotation Processing
注解处理器
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
Android分享 Q群:315658668
【Android】如何实现ButterKnife的更多相关文章
- Android 注解工具 ButterKnife
Butter Knife 是 Android 视图字段和方法绑定,使用注解处理来生成样板代码. 主要特性: 在字段使用 @FindView消除findViewById调用 使用 @FindViews在 ...
- Android 依赖注入 ButterKnife 基本使用
ButterKnife 是一个快速 Android View 注入框架,开发者是Jake Wharton,简单的来说,ButterKnife 是用注解的方式替代findViewById和setXXXL ...
- Android学习笔记- ButterKnife 8.0注解使用介绍
前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种 ...
- Android注解神器 ButterKnife框架
前言: 本人是一个只有几个月工作经验的码小渣.这是我写的第一篇博客,如有不足之处还请大家不要介意,还请大佬可以指出问题. 在这几个月的实战开发中自己也遇到了很多问题,真的是举步艰难啊!!! 在实战开发 ...
- Android开发学习——ButterKnife使用
为了码代码的效率,我们有了ButterKnife;其基本使用如下步骤: 1.在Android Studio的Setting中,下载plugin 2.在整个Project的build.gradle中添加 ...
- android studio报butterknife错误
Error:Execution failed for task ':shipper:javaPreCompileDebug'.> Annotation processors must be ex ...
- Android Studio使用butterknife库绑定控件ID注解
在线导入butterknife的jar包 在Android-app-Open Module Settings下选中module下的app 选择Dependencies,点击右边的“+”,选择第一个:1 ...
- Android Study 之 初识ButterKnife(8.5.1)及简单运用
LZ-Says:突然间不知道说什么好,祝大家编码无bug吧~ 前言 话说,Android开发的兄弟们都知道,每次初始化控件,设置对应的事件.写的那点过程多并且恶心.我们先一块回想下不堪的以前~ 那些年 ...
- Android Butterknife使用方法总结 IOC框架
前言: ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤.是大神J ...
- Android Butterknife(黄油刀) 使用方法总结
前言: ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤.是大神J ...
随机推荐
- [芯片] 3、接口技术·实验三·可编程并行接口8255A
目录 一.实验目的和要求 二.实验原理与背景 2-1.8255A简介 2-2.8255A编程 三.实验具体的内容 3-1.8255方式0实验1 3-2.8255方式0实验2 3-3.8255方式1输出 ...
- easyui使用技巧
1.自定义datagrid字体大小 通过formatter改变字体大小,然后在列中使用: 如下: function formatFontSize(value){ return'<span sty ...
- 带你看懂Dictionary的内部实现
了解Dictionary的开发人员都了解,和List相比,字典添加会慢,但是查找会比较快,那么Dictionary是如何实现的呢? Dictionary的构造 下面的代码我看看Dictionary在构 ...
- JavaScript toFixed function Not Rouding
JavaScript库函数toFixed用来将给定的数字四舍五入为指定的小数位数,W3school上有详细的介绍.众所周知,在处理小数位四舍五入的时候存在两种方式:一种是逢五进一,如5.885保留两位 ...
- [BTS] Error Can't update assemblies.
Removal of the assembly failed. Make sure that all items in the assembly you are trying to remove fu ...
- 使用grunt合并压缩js、css文件
需要了解的知识: 1.nodejs的安装与命令行使用 2.nodejs安装应用 3.grunt的初步了解 本文已假定读者已经熟悉以上知识. 好,我们继续: 任务1:将src目录下的所有zepto及插件 ...
- Oracle数据库建表+添加数据练习
SQL脚本: --建表 --student表+注释 create table student( sno ) not null, sname ) not null, ssex ) not null, s ...
- C# winform的WebBrowser非常规编程(强烈推荐)
本文章被今日头条推荐 1.在WebBrowser中实现抓取301和302协议 在WebBrowser中抓取301和302协议目前官方提供的组件远远不够,需要借助HttpMonitor.dll.这个组件 ...
- CentOS7安装mysql数据库
安装完Centos7,迫不急待的想安装mysql数据库,却没想到走了很多弯路,后来经过查资料,才知道了在Centos7中用MariaDB代替了mysql数据库. 准确来说,本文的标题有点误导的意思,本 ...
- NAS服务器局域网内IPad、手机、电视盒子等联网播放
为把各个移动硬盘和不同电脑的数据进行统一管理,入手了一台希捷 Seagate Business 无内置硬盘 商业级 2盘位 云存储网路存储,经过卖家指点和不断摸索,终于能用了,主要步骤如下: 1. 系 ...