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. 【HDU4471】Homework(矩阵快速幂)

    [HDU4471]Homework(矩阵快速幂) 题面 Vjudge 给定一个数列的前\(m\)项,给定一个和前\(t\)项相关的递推式. 有\(q\)个位置的递推式单独给出,求数列第\(n\)项. ...

  2. 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】

    题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...

  3. Hbase(一)基础知识

    一.Hbase数据库介绍 1.简介 HBase 是 BigTable 的开源 java 版本.是建立在 HDFS 之上,提供高可靠性.高性能.列存储. 可伸缩.实时读写 NoSQL 的数据库系统. N ...

  4. python基础----模块、包

    一 模块                                                                                                 ...

  5. 【DP】【P5080】 Tweetuzki 爱序列

    Description Tweetuzki 有一个长度为 \(n\) 的序列 \(a_1~,~a_2~,~\dots~,a_n\). 他希望找出一个最大的 \(k\),满足在原序列中存在一些数 \(b ...

  6. 洛谷P2398 GCD SUM (数学)

    洛谷P2398 GCD SUM 题目描述 for i=1 to n for j=1 to n sum+=gcd(i,j) 给出n求sum. gcd(x,y)表示x,y的最大公约数. 输入输出格式 输入 ...

  7. 回顾static与final的作用

    static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法: 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享: 用来修饰成员方法,将其变为类方法,可以直接 ...

  8. python学习(十)元类

    python 可以通过`type`函数创建类,也可通过type判断数据类型 import socket from io import StringIO import sys class TypeCla ...

  9. LINUX下时间类API

    (1)常用的时间相关的API和C库函数有9个:time/ctime/localtime/gmtime/mktime/asctime/strftime/gettimeofday/settimeofday ...

  10. UndertowServer+SpringMVC+Thymeleaf模板引擎构建轻量级的web项目

    这两周需要写一个页面来请求另一个服务中的接口,服务器采用了超轻量级的undertow,模板引擎采用的是Thymeleaf,在寻找页面资源位置这个地方难住了我.下面分享一下,这方面的代码. Spring ...