# findViewById - ButterKnife

> [http://jakewharton.github.io/butterknife/](http://jakewharton.github.io/butterknife/)

ButterKnife是Jake Wharton大神写的一个开源库, 可以用来替代Android中的findViewById语句. ButterKnife采用了注解的方式, 但由于是使用编译时补全代码的方式, 所以对性能的影响微乎其微.

ButterKnife支持以下功能:

* 支持 Activity 中的 View 注入
* 支持 View 中的 View 注入
* 支持 View 事件回调函数注入
* 支持ViewHolder模式注入

具体使用方式可以参考[ButterKnife基本使用](http://www.cnblogs.com/mengdd/p/4595973.html).

ButterKnife需要在Activity的onCreate方法里加入`ButterKnife.bind(this)`语句. 这在BaseActivity中已经写好, 子类无需再写. BaseFragment也一样.

## 小技巧

* ButterKnife配合Android Studio的插件`Android ButterKnife Zelezny`简直是无情, 这个插件可以分析xml文件中的id, 并在代码中自动生成声明代码, 完全不用手写.
*   考虑下面的情况:

    > 一个界面里, 有一个列表, 我们要为列表添加一个头部, 头部里包含了一些用户信息, 我们希望用户信息能跟随着列表一起滚 动, 而不是固定在顶部.

    这个时候我们一般会使用ListView + addHeaderView()方法来实现.

    ```
    final View header = getLayoutInflater().inflate(R.layout.content_home, null);
    listView.addHeaderView(header);
    ```

    header里有一些view需要用findViewById查找出来, 但是header不属于activity的布局xml的一部分, 也就是不能使用ButterKnife直接bind出来, 这个时候怎么办呢? 这种情况就需要使用ButterKnife.bind(Object target, View source)方法. 要使用这个方法我们首先得新建一个内部类:

    ```
      class HeaderViewHolder {
          @Bind(R.id.textView)
          TextView textView;

          // 通过构造函数来初始化ButterKnife
          public HeaderViewHolder(View view) {
              ButterKnife.bind(this, view);
          }

          // 在Activity/Fragment的onDestroy里一定要调用unBind方法
          public void unBind() {
              ButterKnife.unbind(this);
          }

          @OnClick(R.id.button)
          public void onButtonClicked(View view) {
              // 将点击事件传递给Activity
              MainActivity.this.onButtonClicked(view);
          }
      }
    ```

    在Activity中则这么写:

    ```
    final View header = getLayoutInflater().inflate(R.layout.content_home, null);
    HeaderViewHolder headerViewHolder = new HeaderViewHolder(header);

    listView.addHeaderView(header);

    headerViewHolder.textView.setText("text");
    ```

    ```
    public void onButtonClicked(View view) {
       showToast("clicked");
    }
    ```

    ```
    @Override
    public void onDestroy() {
        headerViewHolder.unBind();
        super.onDestroy();
    }
    ```

    逻辑非常简单. 可以看到HeaderViewHolder中, 构造函数和unBind方法几乎不会变化, 因此我们可以写一个基类, 减少重复代码:

    ```
    /**
     * 利用ButterKnife与内部类做额外布局的控件查找
     */
    public class BaseInnerViewHolder {
        public BaseInnerViewHolder(View view) {
            ButterKnife.bind(this, view);
        }

        public void unBind() {
            ButterKnife.unbind(this);
        }
    }
    ```

    新的HeaderViewHolder:

    ```
      class HeaderViewHolder extends BaseInnerViewHolder {
          @Bind(R.id.textView)
          TextView textView;

          public HeaderViewHolder(View view) {
              super(view);
          }

          @OnClick(R.id.button)
          public void onButtonClicked(View view) {
              MainActivity.this.onButtonClicked(view);
          }
      }
    ```
