ButterKnife 这个框架真的很好用,简化了大量的代码,在效率上和手写的代码相比几乎没有损失。虽然会用 ButterKnife,同时 ButterKnife 的原理也要明白。
于是,找到 ButterKnife 最早的 1.0 版本,学习一下它的原理,并模仿一下。
最终效果
在 Activity 中使用注解绑定控件
1 | public class MainActivity extends AppCompatActivity { |
框架根据注解生成的代码如下
1 | public class MainActivity$$ViewInjector { |
项目结构
- app
- annotation
- compiler
- api
app
就是我们的android项目
annotation
定义注解,InjectView
就放在这个 module 中
compiler
注解解析器,生成代码
api
定义 Butterkinfe 的 API,比如我们常用的 Butterknife.bind()
annotation
在 Android Studio 点击 File - New Module - Java Library 新建一个 Java Module
build.gradle 内容如下
1 | apply plugin: 'java' |
然后定义一个注解
1 | import java.lang.annotation.ElementType; |
compiler
有了注解,接着就需要一个注解解析器,去解析注解然后生成代码。
同样的,建立一个 Java Library,build.gradle 的定义如下
1 | apply plugin: 'java' |
在这里引入了 Google 的 auto-service 依赖。它可以用来帮助生成 META-INF 文件
接着就是创建注解解析器,实现 process
方法
1 | (Processor.class) |
这个方法中,主要做了几件事
- 找到所有使用 InjectView 注解的类
- 解析 InjectView 注解的信息
- 根据信息生成代码
api
创建一个 Android Library,建立一个 Views
类
1 | import android.app.Activity; |
因为,我们生成代码的类名是 Activity的类名+$$ViewInjector
。比如一个 Activity 叫 HelloActivity
,那么生成的代码的类名就是 HelloActivity$$ViewInjector
。因此这里利用反射,根据类名的规则找到我们生成的类,调用 inject()
方法。
当然,也可以不使用反射,直接调用生成好的类 HelloActivity$$ViewInjector.inject(Activity activity)
,这样也是可以的。但是有个弊端,每次注解完毕只会,都需要 rebuild 一次 project,等代码生成好之后,才能调用 HelloActivity$$ViewInjector.inject(Activity activity)
。这样也挺麻烦了,还是直接用注解吧。
app
build.gradle 定义如下
1 | apply plugin: 'com.android.application' |
同时在项目的 build.gradle 定义如下
1 | buildscript { |
现在可以使用注解了
1 | public class MainActivity extends AppCompatActivity { |
然后点击 Build - Rebuild Project,就可以在 app - build - generated - source - apt 文件夹中看到生成的代码了
项目源码
https://github.com/okadaNana/ViewInject