Androidの開発をしていて、いちいちfindViewId
やsetOnClickListener
をするのがめんどくさくなってくる。。。
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点に注意
ButterKnife.inject(this, view);
とviewも渡す- 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); } } }
以上!!