Android

さよならButterKnife. 僕はAPTの無いキミが好きだったよ

More than 3 years have passed since last update.

一身上の都合により、ButterKnifeを捨てることにしました。

かなり個人的な理由ですが、ButterKnifeを捨てる理由を挙げていきます。


Androidアプリ開発でのButterKnifeの便利さ

ButterKnifeはいかに便利であるかは、Qiitaで"ButterKnife"と検索すればたくさん出てくると思う。Java標準機能である"Annotation"を駆使して、findViewByIdやsetOnHogeHogeListenerを駆逐してくれる、便利なライブラリだ。

この「findViewByIdやsetListenerの代わりにAnnotationを用いる」という基本的なところは大いに賛同するし、Android Annotationを始めとして幾つかの人気ライブラリはそういった便利さを提供してくれている。


ButterKnifeに足りないもの

ButterKnifeはライブラリプロジェクトでは使えない。これが致命的となった。

Annotationの引数として、Resource id(R.id.**とか)を渡すようになっている。しかし、Androidプロジェクトの仕様としてライブラリプロジェクトでは"R.java"に記述された変数にfinal属性が付与されない。そのため、Annotationの引数として使えない(つまりライブラリプロジェクトでButterKnifeは使えない)という状態になっている。

ButterKnifeのissueでは早くからその問題について議論されているが、現在のところ対応される予定はないようだ。


Not for me.

ButterKnifeは8.x系列で、APTを導入すると発表されているし、既にsnapshotが公開されている。APTは便利だし、DataBindingその他のライブラリも積極的に利用しようとしていて「流行り」ではあると思う。APTは事前にソースコードが生成されるから速度面でも有利になる。

しかし、個人的にはAPTに頼るライブラリ数は少なくしておきたい。


ビルド時間の長大化

開発者のマシンスペックは有限で、APTを無数に利用することは開発のイテレーションが遅くなることと直結する(ただでさえGradleはビルドが遅い)。少しでもビルド速度を向上するためには、万札で殴るか、APT導入数を少なくする等の工夫が必要だ。

また、ButterKnifeが活躍するシーンは基本的にオブジェクトがCreateされた瞬間だけであるため、2016年現在の端末ではRuntimeに処理されてもほぼ問題ないレベルであると考えられる。

我々はIS03やREGZA PHONEをそろそろ忘れるべきだ。


APTはNDKプロジェクトとの共存ができない

AS 2.1現在のプラグイン構成では、Android NDK用プラグインとAPTは共存できなかった。つまり、Android NDKを積極的に使いたい場合はプロジェクト構成をかなり工夫しなければならない(「どろいどたん」アプリ開発では複数のプラグインとプロジェクトを組み合わせて開発している)


APTを導入してもライブラリプロジェクト問題は解決しない

APTはビルド時に問題解決が行われるため、そもそもAnnotation構成ではライブラリプロジェクトに導入することができない。


ButterKnifeのようでButterKnifeではないライブラリを作った

いろいろ調べたうえでButterKnifeを導入したが、結局自分向けのライブラリではなかったようだ。

仕方ないので、ButterKniffe7.0.1系列な使い勝手のまま、ライブラリプロジェクトでも利用可能なライブラリを自分で作ることにした。


MargarineKnife

名前の時点でもうパクリ臭がすごい。個人的にはMargarineよりもButter派だけど、Butterが無いならMargarineを塗ろう。

ButterKnifeからforkしようかとも考えたが、どうせ修正するならButterKnifeの(個人的に思っている)問題も解決したほうが良いということで、1から書きなおしている。


このライブラリの特徴


  • 追加の依存ライブラリが無い

  • 規模が小さいのでソースコードを追いかけるのが簡単

  • ソースコード生成のような迂回路を利用しない

  • ライブラリプロジェクトでも使える(制限あり)


    • final変数が使えない制限はAnnotation固有のものなので、R.id.**の代わりにリソース名を文字列指定するようになっている。



  • ButterKnifeから簡単に移行できる


ライブラリプロジェクトでも使える

リソース名を文字列で指定するオプションを追加実装しているので、ライブラリプロジェクトでも使うことができる。ただし、typoの問題が残るのでその点については諦める。

// ButterKnife 7.0.1 ERROR!

@Bind("View_Id")
ViewGroup mViewGroup;

// MargarineKnife OK!

@Bind(resName = "View_Id")
ViewGroup mViewGroup;

@Click(resName = "View_Id")
void clickView(View view) {
// do
}


最後に

実のところ、ButterKnife7.0.1でもProcessorで暗黙的にコードを生成するらしい。気づかなかった。

もっと良い(not APTな)ライブラリがあったら、そっちに移行したい。