【Android】ButterKnife 简单原理实现

ButterKnifeProcedure

ButterKnife的原理简述

示例代码ButterKnifeProcedure

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

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

极简实现演示

演示代码说明

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

第一步(收集信息)

  1. 在每一个类中找到所有被 FindView 注解的字段
  2. 每一个需要绑定的字段信息都保存为一个 FieldViewBinding 对象,比如:
    @FindView(100)
    View vView1;
    得到:
    new FieldViewBinding(vView1, android.view.View, 100)
    
  3. 将字段分类,获取每一个类的“类数据集”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

时间: 2024-11-18 21:40:21

【Android】ButterKnife 简单原理实现的相关文章

Android butterknife 实现原理

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

异步消息处理机制-Android中Handler原理(续)

异步消息处理线程是指线程启动后会进入一个无限循环,每循环一次,从内部的消息队列里面取出一个消息,并回调相应的消息处理函数.一般在任务常驻,比如用户交互任务的情况下使用异步消息处理线程. 之前在Android中Handler原理里面研究过android里实现异步消息处理线程的方式,基本逻辑如图所示 今天就用java将其简单的模拟出来加深印象,下面的类图是用工具导出的,不太正规,不过能大概看出类之间的关系 Message类:消息类 public class Message { public int

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

Android ButterKnife注入框架

常常听到这么一个口号,叫做“努力做个爱偷懒的程序猿”.显然,Android ButterKnife也在一定程度上帮助了你成为一名偷懒的程序猿.作为Android开发者,你肯定对findViewById(),setOnClickListener(),setOnClickListener()等等非常熟悉,久而久之,是不是厌烦了这些东西,简单没营养,又不得不写,这时候,诸如Android ButterKnife,AndroidAnnotations等开源框架就出现了. ButterKnife新特性:

Android的Root原理

前言 一直很好奇Android Root的原理,恰好最近碰到了一个跟Android默认带Root权限的问题,这里顺便记录一下Android系统root的原理. 原理 Android是基于Llinux内核的开源操作系统,与Ubuntu系统类似,所以在Android里获取root权限其实和在Linux系统下获取root权限是一回事.在Linux系统下获取root权限的方法是在命令行执行sudo或者su,接下来输入提权密码就可以获取root权限了.Android系统其实也是这样,例如应用层程序开发,在

android JNI 简单demo(2)之JNI demo 编写

android JNI 简单demo(2)之JNI demo 编写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25559013 二.JNI 基本要素: 1.编写 含native 方法的java文件. 2.把该文件用javah 生成 Cygwin 编译库时要用到的头文件,既*.h 文件. 3.编写*.c 文件,在*.c文件中,实现 *.h 中的方法. 4.编写mk文件. 5.配置NDK环境. 6.用Cygwin

Butterknife实现原理

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

android MultiDex multidex原理原理下遇见的N个深坑(二)

android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multidex原理(一) 解决和遇到的其它问题,请见下一篇文章:android MultiDex 原理下超出方法数的限制问题(三) 遭遇multidex 愉快地写着Android代码的总悟君往工程里引入了一个默默无闻的jar然后Run了一下~~~~ 经过漫长的等待AndroidStudio构建失败了. 于是

Android Butterknife框架

Android Butterknife框架 注解攻略 时间 2014-02-27 09:28:09  Msquirrel原文  http://www.msquirrel.com/?p=95 一.原理. 最近发现一个很好用的开源框架,蛮不错的,可以简化你的代码,是关于注解的.不多说直接进入使用步骤讲解. 二.步骤. 1.准备阶段,先到官网( http://jakewharton.github.io/butterknife/ )上jar包,下载下来. 2.把下载下来的jar包,放到项目的libs下,