くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

AndroidのViewInjectionライブラリ「Butter Knife」を使って楽をする

Androidの開発をしていて、いちいちfindViewIdsetOnClickListenerをするのがめんどくさくなってくる。。。

Butter Knifeはそれのめんどくささを楽にするライブラリらしい。その導入時の備忘録。

サンプルのXMLはこんな感じ

layout/sample.xmlとしてこんなのがあるとする。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <ImageView
        android:id="@+id/empty_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_empty" />
</LinearLayout>

ActivityでViewをInjectionする

アノテーション(@InjectView)で、findViewIdと同じことをやってくれます!

InjectionするにはsetContentViewのあとに、ButterKnife.inject(this);とするだけ!

楽ちん&スッキリ♪

public class MyActivity extends Activity {
  @InjectView(android.R.id.list)
  ListView mListView;

  @InjectView(R.id.empty_image)
  View mEmptyView;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sample);
    ButterKnife.inject(this);
  }

OnClick系もInjectionできる

public class MyActivity extends Activity {
  @InjectView(android.R.id.list)
  ListView mListView;

  @InjectView(R.id.empty_image)
  View mEmptyView;

  @OnItemLongClick(android.R.id.list)
  boolean onItemLongClick(int position) {
    //Listのアイテムが押された時の動作
  }

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sample);
    ButterKnife.inject(this);
  }

アノテーション(@OnItemLongClick)を使うことで、ListViewのOnItemLongClickもいんじぇくしょんできる!

これのいいところは、引数も省略できること!

通常のやり方だと、4つの引数を取らなければならないけど、使わない奴が多くて面倒。。。

mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
  @Override
  public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
    return false;
  }
});

でも、ButterKnifeを使えば、引数を省略できてスッキリかける!

以下のアノテーションなども用意されているので、リスナー系も対応できそう!

@OnClick(android.R.id.list)
@OnLongClick(android.R.id.list)
@OnItemClick(android.R.id.list)
@OnItemLongClick(android.R.id.list)

FragmentでViewをInjectionするときは、viewも指定する

何も考えずにFragmentでもActivityと同じようにしていたらダメだった。。。

Fragmentの場合は、以下の2点に注意

  1. ButterKnife.inject(this, view);とviewも渡す
  2. Viewが破棄されるときに、ButterKnife.reset(this);を呼ぶ
public class MyFragment extends Fragment {
  @InjectView(android.R.id.list)
  ListView mListView;

  @InjectView(R.id.empty_image)
  View mEmptyView;

  @Override
  View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.sample, container, false);
    ButterKnife.inject(this, view);
    return view;
  }

  @Override
  void onDestroyView() {
    super.onDestroyView();
    ButterKnife.reset(this);
  }
}

ListのAdapterでもButter Knifeを

こんな感じで、ViewHolderを作ってInjectionさせるらしい!

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.title.setText("This is title");
    holder.subTitle.setText("これはサブタイトルです");

    return view;
  }

  static class ViewHolder {
    @InjectView(R.id.title) TextView title;
    @InjectView(R.id.sub_title) TextView subTitle;

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

以上!!

[PR] めもらばではこんなあぷりを作っています!

参考にしたサイト様