[Android]ButterKnife の View Injection コードを一発自動生成するプラグイン『ButterKnifeZelezny』

スクリーンショット 2015-02-16 18.49.35

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Butter Knife 使ってますか?

Butter Knifeとは Jake Wharton氏が公開しているAndroidの View "injection" ライブラリーです。

こんな感じでアノテーションを使ってfindViewByIdを記述せずにViewを参照することができます。

class ExampleActivity extends Activity {
  
  @InjectView(R.id.user) EditText username;
  @InjectView(R.id.pass) EditText password;
  
  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.inject(this);
    // TODO Use "injected" views...
  }
}

Jake Wharton : Butter Knife | github.com

このライブラリを使うと、findViewByIdから解放されて作業がはかどりますね。今回は@InjectViewについてのお話ですが、この他にも@OnClick@OnItemSelectedなど、コーディングを加速させてくれるものがいくつもあるので非常にオススメです。

確かにコード量は減るけど。。。

いくらコード量が減ったとは言え、当然全く記述しなくてよいわけではありません。(補完は効きます)

@InjectView(Viewのid) 型 変数名;

レイアウトにViewがそれほど多くない場合には全く気にならないかもしれませんが、Viewが多くなるにつれて面倒になってきます。
そこで、そんな面倒臭さをスッキリ解消してくれるプラグイン

『ButterKnifeZelezny』

をご紹介します!

ライブラリ導入

まずは、Butter Knifeを導入します。お好きな方法でどうぞ。

一番早い方法

build.gradle(Module: app)dependenciesに以下を記述する。

compile 'com.jakewharton:butterknife:6.1.0'

よくやる方法

Project Structure > Dependenciesから追加します。
まずは、Module Settingを開きます。


スクリーンショット 2015-02-16 18.58.23

Dependenciesタブを選択して、左下の+ボタンをクリックします。1 Library dependencyを選択すると、Choose Library Dependencyウィンドウが開くので、ここでbutterknifeで検索します。
すると、検索結果が表示されるのでcompile 'com.jakewharton:butterknife:6.1.0'を選択してOKをクリックします。


スクリーンショット 2015-02-16 19.00.08 スクリーンショット 2015-02-16 19.00.19

そうすると、DependenciesButter Knifeが追加されます。これで、一番早い方法と同じ状態になります。
毎回ライブラリ名の記述を覚えているわけではないので、こんな風にパパッと検索して追加することが多いです。。

プラグイン導入

いよいよ『ButterKnifeZelezny』プラグインを導入します。
Android Studio > Preferences... > Pluginsとたどってプラグインの設定を表示します。


スクリーンショット 2015-02-16 21.01.48

Browse Repositories...ボタンをクリックすると公開されているプラグインがずらずらと表示されます。検索バーにbutterくらいまで入力するとAndroid ButterKnife Zeleznyが表示されると思います。 ウィンドウ右側の緑色のボタンInstall Pluginをクリックすると、Android Studio を再起動してくれと言われるので再起動してください。Android Studio が再起動するとプラグインが有効になっています。

コードを一発自動生成

ライブラリとプラグインの導入ができたとろこで、本題のView Injection コードを一発自動生成です。

必要なもの

  • レイアウト.xml
  • View のandroid:id

まず、レイアウトファイルが必要です。そしてView Injectionしたい View に id を付けておきます。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:text="@string/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <RadioButton
        android:id="@+id/radioButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New RadioButton"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

</RelativeLayout>

次に、Activity を表示します。
そして、R.layout.activity_mainにカーソルを合わせて右クリック > Generate...もしくはcommand + Nで Generate メニューを開きます。

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}

スクリーンショット 2015-02-17 11.13.03

Generate メニューからGenerate Butterknife Injectionsを選択します。


スクリーンショット 2015-02-17 11.17.14

左から、コード生成の有無を切り替えるチェックボックス、View の種類、レイアウトファイルで指定した id 、変数名となっています。ここで注目して頂きたいのは、レイアウトファイルでばらばらのフォーマットで指定した id が Android の命名規則に則ったかたちに整形されています。id のフォーマット揃えろよ!ってお話なのですが、このような場合にもうまいことやってくれます。
更に、変数名にプレフィックスmが付いていますが、ここらへんはプラグインの設定から変更可能です。

ここまできたら、あとはConfirmをクリックするだけです。

結果はこちら

public class MainActivity extends ActionBarActivity {

    @InjectView(R.id.text_view)
    TextView mTextView;
    @InjectView(R.id.button)
    Button mButton;
    @InjectView(R.id.radioButton)
    RadioButton mRadioButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this); // View Inject
        // ここからViewのインスタンスが使えます
    }

}

アノテーションの付いた View とButterKnife.inject(this);が追加されました。インジェクトを実行した直後から View を使うことができます。
言葉で書くと長くなりますが、実際は一瞬です。

このように、何度も同じようなことを自分で書かなくてよくなるので作業がはかどります。今回のサンプルのように、レイアウトファイルを完成させてからではなくても、どのようなタイミングでも実行することができます。ただし、ButterKnife Zeleznyでコードを生成する度にButterKnife.inject(this);が挿入されるので注意してください。

さいごに

今回は Activity でやってみましたが、Fragment でも問題なく使用できます。これはプラグインのお話ではありませんが、Fragment で使う場合にはonDestroyViewButterKnife.reset(this);の記述をお忘れなく。

INJECTION RESET

Fragments have a different view lifecycle than activities. When injecting a fragment in onCreateView, set the views to null in onDestroyView. Butter Knife has a reset method to do this automatically.

Butter Knife