ButterKnife(黄油刀) 是大名鼎鼎的 JakeWharton大神 所写的注解框架,目的是为了将我们从大量的
findViewById()和 监听类中解脱出来,从而将更多的关注点在业务需求上。

前言
ButterKnife 是一个通过注解的方式将 变量 和 方法 与 Android 视图绑定的框架。
使用 ButterKnife,我们能够:
- 通过
@BindView替代大量的findViewById(); - 在 list 和 array 中组织多个视图,并能够即时通过 actions, setters 或者 properties 来操作它们;
- 通过
@OnClick或别的注解方式来替代大量的监听内部类; - 通过资源注解替代资源查询。
如何在项目中使用?
本文只说在 Android Studio 中如何来使用(你要问我为什么不把 eclipse 中使用的方法也写上来,我只想说,大兄弟,弃了 eclipse 吧!)
1.第一步:
项目根目录的 build.gradle 文件的 dependencies 中添加 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8',如图:

2.第二步:
app 目录下的 build.gradle 中配置 apply plugin: 'com.neenbedankt.android-apt';
dependencies 中配置:
1 | compile 'com.jakewharton:butterknife:8.0.1' |
如图:

懒人必备:ButterKnifeZelezny 插件
功能介绍:帮助我们快速生成布局文件中的 view 对应的变量,省时省力。点击 Setting -> Plugins -> Browse repositores;

如上图所示,在搜索框中输入 butterknife,搜索列表中人气最高的就是 ButterKnifeZelezny 插件,点击右边的 安装 按钮,安装完成后,重启 Android studio 即可使用该插件了。
如何使用插件?
在需要自动生成绑定关系的 布局文件(如:R.layout.main) 上 右键, 点击 Generate -> Generate Butterknife Injections, 如下图:

在窗口中选中,需要生成的变量,点击 confirm 即可:

详解
通过 @BindView, ButterKnife 能够自动的在相应的 layout 中查找到对应的 id,并与注解的变量绑定在一起。
1 | class ExampleActivity extends Activity { |
ButterKnife 并不是运用反射的原理,视图与变量的绑定是在编译时动态生成代码,原理是通过 bind 委托,上面的注解会变成如下所示的代码:
1 | public void bind(ExampleActivity activity) { |
Resource 绑定
通过预定义的注解与相应的字段绑定,如 @BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString.
1 | class ExampleActivity extends Activity { |
非 Activity 如何绑定
你可以在提供的根视图的任何对象内执行绑定,例如下面的 fragment:
1 | class ExampleActivity extends Activity { |
而在 list adapter 中,你可以通过 ViewHolder 的方式:
1 | public class MyAdapter extends BaseAdapter { |
View List
你可以将多个 view 放到一个 list 或者 数组 中。
1 | ({ R.id.first_name, R.id.middle_name, R.id.last_name }) |
通过 apply() 能够让你即时改变所有 view 的行为。
1 | ButterKnife.apply(nameViews, DISABLE); |
Action 和 Setter 接口也同样能够允许你指定一些简单的行为。
1 | static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() { |
Android 中的一些属性也能够被使用在 apply() 方法中:
1 | ButterKnife.apply(nameViews, View.ALPHA, 0.0f); |
Listener 绑定
Listeners 同样能够动态的配置到某个方法上:
1 | (R.id.submit) |
所有监听方法中的参数都是可选择的:
1 | (R.id.submit) |
你可以在方法中指定一个类型:
1 | (R.id.submit) |
将多个 ID 指定为用同一个方法处理:
1 | ({ R.id.door1, R.id.door2, R.id.door3 }) |
自定义类型的 View 可以不用指定 ID 来绑定到 listener:
1 | public class FancyButton extends Button { |
绑定重置
相比较 Activity, Fragment 拥有不同的生命周期方法。当你在 onCreateView() 绑定了一个 fragment, 在 onDestroyView() 方法中将 view 设置为 null.
当你调用 bind() 方法时,ButterKnife 会返回一个 Unbinder 实例,你只需要调用其 unbind() 方法即可解绑。
1 | public class FancyFragment extends Fragment { |
选择性绑定
默认情况下,@Bind 和 监听绑定 都是需要的,但是当目标视图不存在时,会抛异常。
为了防止它出现,我们可以在绑定的变量上加上 @Nullable 注解或者在方法上加上 @Optional 注解。
注意:
@Nullable可以被使用在任何变量上,你只需导入 “supprot-annotations” 依赖即可。
1 | @Nullable annotation from Android's "support-annotations" library. |
多个方法监听
每个方法也可以绑定多个回调方法,这些方法有一个默认的回调,你也可以通过 callback 参数来指定替代的方法。
1 | (R.id.list_view) |
彩蛋
ButterKnife 还提供了 findById() 方法,通过它,你也能够在布局文件中找到相应的 view, Activity, Dialog …
此方法通过泛型,来动态对返回值做转换。
1 | View view = LayoutInflater.from(context).inflate(R.layout.thing, null); |
参考文献: