Android (Kotlin) のコード簡略化ツールを調べてみた
この種のツールは何と呼ぶのが正しいのかわかりませんが、アノテーションを使って定型コードを簡略化できるツールについて調べてみました。
AndroidAnnotations v4.3.1
まずは、この種のツールの(多分)走りである AndroidAnnotations です。
機能は、Activity に対するレイアウトの指定から、スレッドや REST クライアントなど、多岐に渡ります。
Ref. AvailableAnnotations · androidannotations/androidannotations Wiki
若干癖があるのが、ビルド時にサブクラスを生成するところです。
例えば、MyActivity
に @EActivity
を付けた場合、MyActivity_
というサブクラスができるので、マニフェストファイルでは、MyActivity_
の方で記述する必要があります。
Kotlin で使う時の注意点は、以下の記事が参考になります:
AndroidAnnotations with Kotlin - Qiita
まず、Java と同様に書いてみます:
@EActivity(R.layout.activity_main) open class MainActivity : AppCompatActivity() { @ViewById(R.id.name) var name: TextView? = null override open fun onCreate(savedInstanceState: Bundle?) { name?.setText("something") .....
ビルドすると、org.androidannotations.annotations.ViewById cannot be used on a private element
というエラーになってしまいます。
(エラーは app/build/generated/source/kapt/androidannotations.log
に出力されます。)
「android - AndroidAnnotations - ViewById cannot be used on a private element - Stack Overflow」によると、lateinit
を使え、となっているので、書き換えてみます:
@ViewById(R.id.name) lateinit var name: TextView
そうするとビルドは通りますが、実行時に kotlin.UninitializedPropertyAccessException: lateinit property toolbar has not been initialized
というエラーになってしまいます。
このエラーは結局解消できませんでした。
Butter Knife v8.8.1
次に Butter Knife です。
Butter Knife は、AndroidAnnotations に比べると、機能が絞り込まれていて、できるのは、ビュー、リソース、リスナーのバインディングぐらいです。
AndroidAnnotations のようにマニフェストファイルでの指定が変わることはないので、手軽に使えます。
まずは、AndroidAnnotations と同様に、nullable で定義してみます:
@BindView(R.id.name) var name: TextView? = null ..... name?.setText("something")
これはうまく動作しました。
ちなみに、lateinit を使うと、AndroidAnnotations と同様の実行時エラーが出ます。
以下の issue でも解決策がありません:
Kotter Knife v0.1.0
Kotter Knife は Butter Knife の Kotlin 版です。
Kotter Knife を使うと、シンプルに書けるようになります:
val name: TextView by bindView(R.id.name)
ちなみに by
は、Kotlin の Delegated Properties という機能です。
Kotlin Android Extensions
Kotlin Android Extensions は、findViewById
を省略できるようにするもので、Android Studio の Kotlin プラグインに含まれています。
これを使うと、コードは以下のようになります:
// Using R.layout.activity_main from the main source set import kotlinx.android.synthetic.main.activity_main.* class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) textView.setText("Hello, world!") // Instead of findViewById(R.id.textView) as TextView } }
(引用元:Kotlin Android Extensions - Kotlin Programming Language)
アノテーションも不要なので、非常にシンプルですね。
ただし、import
の部分がどうしても解決できず、動きませんでした。
その他
DIフレームワークでも同様のことができるようですが、今回は調べていません。
まとめ
結局、動いたのは Butter Knife と Kotter Knife だけでした。
Kotlin で使う場合は Kotter Knife の方が良さそうですね。