findViewById - ButterKnife

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

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

ButterKnife支持以下功能:

  • 支持 Activity 中的 View 注入

  • 支持 View 中的 View 注入

  • 支持 View 事件回调函数注入

  • 支持ViewHolder模式注入

具体使用方式可以参考ButterKnife基本使用.

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);
          }
      }

Last updated