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. 一些noip模拟题一句话题解

    Problem A: 序列 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 12  Solved: 9[Submit][Status][Web Boar ...

  2. Yura

    Portal --> broken qwq Description ​  给你一个长度为\(n\)的序列\(a\)和一个正整数\(k\),求满足如下条件的区间\([l,r]\)的数量:\((\s ...

  3. python基础----迭代器、生成器、协程函数及应用(面向过程实例)

    一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代 ...

  4. PHP 多线程采集

    function curl_multi($urls) { if (!is_array($urls) or count($urls) == 0) { return false; } $num=count ...

  5. mac下php添加openssl扩展

    进入php源码目录 cd ext/openssl mv config0.m4 config.m4 phpize && ./configure  && make & ...

  6. poj 1696 (计算几何基础)

    poj 1696 Space Ant 链接:http://poj.org/problem?id=1696 题意:在坐标轴上,给定n个点的 id 以及点的坐标(xi, yi),让你以最底端点开始,从右依 ...

  7. WIFI Direct(Wi-Fi P2P)

    Wi-Fi Direct技术是Wi-Fi产业链向蓝牙技术发起的挑战,它试图完全取代蓝牙 Wi-Fi Direct是一种点对点连接技术,它可以在两台station之间直接建立tcp/ip链接,并不需要A ...

  8. 跟我一起写Makefile(六)

    使用条件判断—————— 使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支.条件表达式可以是比较变量的值,或是比较变量和常量的值. 一.示例 下面的例子,判断$(CC)变量是否“gc ...

  9. gulp教程之gulp-autoprefixer

    现在浏览器的种类很多,不同浏览器的内核不同,同一浏览器也有很多不同的版本,很多css属性为了兼容浏览器需要加上特定的前缀,比如chrome的前缀是-webkit-,firefox前缀是-moz-等. ...

  10. [Ctsc2014]企鹅QQ

    3555: [Ctsc2014]企鹅QQ Time Limit: 20 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description P ...