Android ButterKnife框架學習

基本介紹

使用@BindView註解,並傳入控件Id,ButterKnife就可以自動的找到佈局中相對應的控件並且綁定到類成員上。

class ExampleActivity extends Activity {
  @BindView(R.id.title) TextView title;
  @BindView(R.id.subtitle) TextView subtitle;
  @BindView(R.id.footer) TextView footer;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
    // TODO Use fields...
  }
}

需要在setContentView調用後調用ButterKnife.bind(this)。

相對於緩慢的反射而言,ButterKnife是生成的,因此不需要擔心性能問題。

這些生成的代碼和下面的代碼效果大致是一樣的

public void bind(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);
}

資源綁定

使用@BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString來綁定一些提前定義好的資源。只需要把ID傳進去,他就會綁定相應的資源。

class ExampleActivity extends Activity {
  @BindString(R.string.title) String title;
  @BindDrawable(R.drawable.graphic) Drawable graphic;
  @BindColor(R.color.red) int red; // int or ColorStateList field
  @BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
  // ...
}

非Activity綁定

只要傳進去你的根佈局,你就可以在任意的對象中進行綁定

例如,在Fragment中

public class FancyFragment extends Fragment {
  @BindView(R.id.button1) Button button1;
  @BindView(R.id.button2) Button button2;

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fancy_fragment, container, false);
    ButterKnife.bind(this, view);
    // TODO Use fields...
    return view;
  }
}

另一個常見的用法是在ListView的ViewHolder中

public class MyAdapter extends BaseAdapter {
  @Override public View getView(int position, View view, ViewGroup parent) {
    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 view;
  }

  static class ViewHolder {
    @BindView(R.id.title) TextView name;
    @BindView(R.id.job_title) TextView jobTitle;

    public ViewHolder(View view) {
      ButterKnife.bind(this, view);
    }
  }
}

View列表

你可以把多個View放到列表中

@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;

apply方法允許你一次性的對列表中的所有控件進行操作

ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);

Action和Setter接口可以讓你制定一些簡單的工作

static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
  @Override public void apply(View view, int index) {
    view.setEnabled(false);
  }
};
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
  @Override public void set(View view, Boolean value, int index) {
    view.setEnabled(value);
  }
};

監聽器綁定

監聽器可以自動的配置到方法上

@OnClick(R.id.submit)
public void submit(View view) {
  // TODO submit data to server...
}

監聽器的所有參數都是可選的

@OnClick(R.id.submit)
public void submit() {
  // TODO submit data to server...
}

定義一個具體的類型他將自動被轉化

@OnClick(R.id.submit)
public void sayHi(Button button) {
  button.setText("Hello!");
}

指定多個Id的控件綁定到共同的

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

自定義View可以綁定他們的監聽器不需要通過指定id

public class FancyButton extends Button {
  @OnClick
  public void onClick() {
    // TODO do something!
  }
}

重置綁定

Fragment與Activity生命週期不一樣,我們在onCreateView中綁定Fragment,在onDestroyView中將view設爲null。當你調用bind的時候,ButterKnife返回了一個Unbinder實例。你需要在適當的生命週期中調用unBind()方法。

public class FancyFragment extends Fragment {
  @BindView(R.id.button1) Button button1;
  @BindView(R.id.button2) Button button2;
  private Unbinder unbinder;

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fancy_fragment, container, false);
    unbinder = ButterKnife.bind(this, view);
    // TODO Use fields...
    return view;
  }

  @Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }
}

多個方法的監聽器

當一個監聽器包含多個回調函數時,使用方法注入能夠對其中任何一個函數進行綁定。每一個註解都會綁定到一個默認的回調。當然,你也可以指定callback參數:

@OnItemSelected(R.id.list_view)
void onItemSelected(int position) {
  // TODO ...
}

@OnItemSelected(value = R.id.maybe_missing, callback = NOTHING_SELECTED)
void onNothingSelected() {
  // TODO ...
}

findById

ButterKnife也提供了一個findById的方法來簡化findViewById在view,activity,dialog中的調用。他是用泛型對返回類型進行判斷並進行強轉。

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

如果你只是用這個方法就靜態引入ButterKnife.findById就可以了。

使用

在你的(project)的build.gradle中添加

buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

在你的(module)的build.gradle中添加

apply plugin: 'android-apt'

android {
  ...
}

dependencies {
  compile 'com.jakewharton:butterknife:8.1.0'
  apt 'com.jakewharton:butterknife-compiler:8.1.0'
}

確保apply這一行放在了你的文件的頂部。

更詳細官方的介紹請看官方使用教程

ButterKnife在代碼和例子都可以在git上看到

我個人的git地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章