Butter Knife:一个安卓视图注入框架

2014年5月8日 星期四

14:52

官网: http://jakewharton.github.io/butterknife/

GitHub地址: https://github.com/JakeWharton/butterknife

JavaDocs地址: http://jakewharton.github.io/butterknife/javadoc/

注:本随笔翻译自官网,做了一些整理和注释。来自我的OneNote笔记

大纲:

  1. @InjectView (Activity,Fragment)
  2. @InjectViews
  3. apply
  4. @OnClick
  5. reset
  6. @Optional
  7. @OnItemSelected
  1. TextView firstName = ButterKnife.findById(view, R.id.first_name);

Activity的注入方法:

//基本使用方法:在onCreate方法中调用ButterKnife.inject(this),然后就可以调用注解了

class ExampleActivity extends Activity {

@InjectView(R.id.title) TextView title;

@InjectView(R.id.subtitle) TextView subtitle;

@InjectView(R.id.footer) TextView footer;

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.simple_activity);

ButterKnife.inject(this);

// TODO Use "injected" views...

}

}

这个注入不是通过反射实现了(反射比较慢),而是直接生成代码。上面的三个注入最后生成如下的代码

public void inject(ExampleActivity activity) {

activity.subtitle = (android.widget.TextView) activity.findViewById(2130968578);

activity.footer = (android.widget.TextView) activity.findViewById(2130968579);

activity.title = (android.widget.TextView) activity.findViewById(2130968577);

}

Fragment的注入方法:

public class FancyFragment extends Fragment {

@InjectView(R.id.button1) Button button1;

@InjectView(R.id.button2) Button button2;

@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.fancy_fragment, container, false);

//仅仅是这里的区别

ButterKnife.inject(this, view);

// TODO Use "injected" views...

return view;

}

}

简化ViewHolder的使用 

public class MyAdapter extends BaseAdapter {

@Override public View getView(int position, View view, ViewGroup parent) {

//ViewHolder是一个普通的类,这个类包含了一个Adapter需要的所有View,然后设置到了tag中,方便复用

ViewHolder holder;

if (view != null) {

holder = (ViewHolder) view.getTag();

} else {

view = inflater.inflate(R.layout.whatever, parent, false);

holder = new ViewHolder(view);

view.setTag(holder);

}

holder.name.setText("John Doe");

// etc...

return convertView;

}

//这里是ViewHolder:可以这样进行注入

static class ViewHolder {

@InjectView(R.id.title) TextView name;

@InjectView(R.id.job_title) TextView jobTitle;

public ViewHolder(View view) {

ButterKnife.inject(this, view);

}

}

}

注入一个View列表:@InjectViews

//注入一个View列表

@InjectViews({ R.id.first_name, R.id.middle_name, R.id.last_name })

List<EditText> nameViews;

//调用apply方法批量给View设置属性

ButterKnife.apply(nameViews, DISABLE);

ButterKnife.apply(nameViews, ENABLED, false);

//其中,DISABLE和ENABLED是两个接口的实现:Action,Setter

static final Action<View> DISABLE = new Action<>() {

@Override public void apply(View view, int index) {

view.setEnabled(false);

}

}

static final Setter<View, Boolean> ENABLED = new Setter<>() {

@Override public void set(View view, Boolean value, int index) {

view.setEnabled(value);

}

}

////View所有的属性都可以在apply方法中调用

ButterKnife.apply(nameViews, View.ALPHA, 0);

点击监听器的注入:OnClickListener -> @OnClick

//简单使用

@OnClick(R.id.submit)ren

public void submit() {

// TODO submit data to server...

}

//你可以传入一个参数,Butter Knife会自动将注入的View转换为对应的类型

@OnClick(R.id.submit)

public void sayHi(Button button) {

button.setText("Hello!");

}

//当然,也可以指定多个视图的IDs,用来进行通用的处理

@OnClick({ R.id.door1, R.id.door2, R.id.door3 })

public void pickDoor(DoorView door) {

if (door.hasPrizeBehind()) {

Toast.makeText(this, "You win!", LENGTH_SHORT).show();

} else {

Toast.makeText(this, "Try again", LENGTH_SHORT).show();

}

}

注入的重置:reset

Fragment中,我们需要在onDestroyView中设置这些View为null,但是只要调用reset方法,Butter Knife会自动执行这个步骤。

public class FancyFragment extends Fragment {

@InjectView(R.id.button1) Button button1;

@InjectView(R.id.button2) Button button2;

@Override View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.fancy_fragment, container, false);

ButterKnife.inject(this, view);

// TODO Use "injected" views...

return view;

}

@Override void onDestroyView() {

super.onDestroyView();

ButterKnife.reset(this);

}

}

可选的注入 @Optional

默认情况下,@InjectView和@OnClick注入是必须了,所以,如果找不到目标View就会抛出异常。如果想抑制这种情况,可以通过@Optional注解:

@Optional @InjectView(R.id.might_not_be_there) TextView mightNotBeThere;

@Optional @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {

// TODO ...

}

多方法的监听@OnItemSelected

有些监听注解响应的方法有多个回调函数,所以,我们可以通过指定回调参数来实现多个回调方法的绑定。

@OnItemSelected(R.id.list_view)

void onItemSelected(int position) {

// TODO ...

}

@OnItemSelected(value = R.id.maybe_missing, callback = NOTHING_SELECTED)

void onNothingSelected() {

// TODO ...

}

BONUS:其实就是一个方便的静态方法而已

一般我们实例化一个View的时候是通过findById(id),然后强制转换实现的,这样的代码看着不雅观。所以,ButterKnife有一个方法自动帮我们进行这样的转换(Context可以为View和Activity),如下面的例子:

View view = LayoutInflater.from(context).inflate(R.layout.thing, null);

TextView firstName = ButterKnife.findById(view, R.id.first_name);

TextView lastName = ButterKnife.findById(view, R.id.last_name);

ImageView photo = ButterKnife.findById(view, R.id.photo);

最新版本:5.0.1

集成方法

Maven:

<dependency>

<groupId>com.jakewharton</groupId>

<artifactId>butterknife</artifactId>

<version>5.0.1</version>

</dependency>

Gradle:

  1. 添加依赖

compile 'com.jakewharton:butterknife:5.0.1'

  1. 消除lint warning

lintOptions {

disable 'InvalidPackage'

}

  1. Some configurations may also require additional exclusions.

packagingOptions {

exclude 'META-INF/services/javax.annotation.processing.Processor'

}

Procuard配置:(这个配置是为了打包apk的时候不至于把你的那些貌似没有用过的程序片段给删掉了)

-dontwarn butterknife.internal.**

-keep class **$$ViewInjector { *; }

-keepnames class * { @butterknife.InjectView *;}

Butter Knife:一个安卓视图注入框架的更多相关文章

  1. Objection, 一个轻量级的Objective-C依赖注入框架

    简介 项目主页:https://github.com/atomicobject/objection 实例下载: https://github.com/ios122/ios122 Objection 是 ...

  2. 开源安卓Http文件下载框架file-downloader的使用

    file-downloader FileDownloader(https://github.com/wlfcolin/file-downloader)是本人开源的一个安卓Http文件下载框架,是根据自 ...

  3. Android RoboGuice开源框架、Butter Knife开源框架浅析

    Google Guice on Android(RoboGuice) 今天介绍一下Google的这个开源框架RoboGuice, 它的作用跟之前讲过的Dagger框架差点儿是一样的,仅仅是Dagger ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入[4]:一个Mini版的依赖注入框架

    在前面的章节中,我们从纯理论的角度对依赖注入进行了深入论述,我们接下来会对.NET Core依赖注入框架进行单独介绍.为了让读者朋友能够更好地理解.NET Core依赖注入框架的设计与实现,我们按照类 ...

  5. Butter Knife 黄油刀

    简介 Github:https://github.com/JakeWharton/butterknife  文档 特点: 采用注解的方式实现强大的View绑定和Click事件处理功能,简化代码,提升开 ...

  6. View注入框架:Butterknife简单使用

    View注入框架 下载地址 1.Activity Binging 通过@Bind凝视字段,Butter Knife能够通过View的ID自己主动找到并把对应的视图布局. class ExampleAc ...

  7. ButterKnife--View注入框架的使用

    作为一名Android开发,是不是经常厌烦了大量的findViewById以及setOnClickListener代码,而ButterKnife是一个专注于Android系统的View注入框架,让你从 ...

  8. ButterKnife--View注入框架

    俗话说,不会偷懒的程序员不是好程序员!作为一名Android的开发者,我们已经厌烦了经常写大量的findViewById以及setOnClickListener代码.而ButterKnife是一个专注 ...

  9. Butter Knife使用详解

    Butter Knife Github地址: https://github.com/JakeWharton/butterknife 官方说明给出的解释是 Bind Android views and ...

随机推荐

  1. BZOJ1089 [SCOI2003]严格n元树 【dp + 高精】

    Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d (根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严 ...

  2. 开放接口/RESTful/Api服务的设计和安全方案

    总体思路 这个涉及到两个方面问题:一个是接口访问认证问题,主要解决谁可以使用接口(用户登录验证.来路验证)一个是数据数据传输安全,主要解决接口数据被监听(HTTPS安全传输.敏感内容加密.数字签名) ...

  3. poj 1273 裸 网络流 (dinic)

    Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover ...

  4. 树莓派更改vnc分辨率

    参考链接:https://raspberrypi.stackexchange.com/questions/56421/how-to-increase-resolution-on-latest-rasp ...

  5. 图片虚拟目录--即图片保存在window硬盘上面

    这个是图片保存在电脑的硬盘上面的图片上传设置,既不是在web工程中,也不是在专门的图片服务器中,下面是配置方法: r 这里的Document base 我们这里设置为F:\images 如果在浏览器访 ...

  6. bzoj 1030 AC自动机+dp

    代码: //先把给的单词建AC自动机并且转移fail,然后d[i][j]表示构造的文章到第i位时处在字典树的第j个节点的不包含单词的数量,最后用总的数量26^m //-d[m][0~sz]即可.其中不 ...

  7. dfs.datanode.du.reserved 预留空间不生效的问题

    生产环境(cdh5.5.1)遇到一个问题:已经设置 dfs.datanode.du.reserved预留空间为20G,但是磁盘仍然被写满了. 当挂载磁盘作为datanode的存储空间,如果磁盘大小为2 ...

  8. nginx如何配置虚拟主机

    server { listen 80; #listen [::]:80 default_server ipv6only=on; server_name local.presion.caomall.ne ...

  9. TestNG指南

    转载自:http://blog.csdn.net/bigapplestar/article/details/7300137 今天突然收到通知,统一改用TestNG写测试用例,开始查这方面的资料,学习一 ...

  10. $(window).load与$(document).ready的区别

    刚好今天学了用jQuery实现瀑布流的用法,但加载时发现了一个小小的问题,那就是分别用$(window).load与$(document).ready实现加载时,$(document).ready的布 ...