AndroidでKotlinが使えるようになったのでかなり楽にプログラミングできるようになりましたが、それでもまだAndroidAnnotationsを使った方が便利なことは多いので、私はほぼ全てのAndroidアプリで使っています。
Kotlinプロジェクトでアノテーションプロセッシングをするためにはkaptを使います。android-aptプラグインを使ったことがあるならほとんど追加で覚えることはありません。apt
で設定していた依存ライブラリをkapt
で設定すれば良いだけです。
以下がKotlin AndroidプロジェクトにAndroidAnnotationsを導入するための設定です。先頭にapply plugin: 'kotlin-kapt'
を追加するのと、依存ライブラリにkapt 'org.androidannotations:androidannotations:4.3.1'
と compile 'org.androidannotations:androidannotations-api:4.3.1'
を追加するだけです。
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' // これを追加
...
dependencies {
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
// AndroidAnnotations
kapt 'org.androidannotations:androidannotations:4.3.1'
compile 'org.androidannotations:androidannotations-api:4.3.1'
// OrmLite
// kapt 'org.androidannotations:ormlite:4.3.1'
// compile 'org.androidannotations:ormlite-api:4.3.1'
// Rest client
// kapt 'org.androidannotations:rest-spring:4.3.1'
// compile 'org.androidannotations:rest-spring-api:4.3.1'
}
単純なプロジェクトならこれで動きますが、ビルドフレーバーを設定していたりすると上手く動かないときがあります。そういう場合の対処法は……
現在調査中です。
注意
AndroidAnnotationsを使っていたJavaコードをそのままKotlinに変換しただけではうまく動かない箇所がいくつかあります。
open修飾子を付ける
JavaとKotlinの大きな違いは、Kotlinのクラス・メソッドは何も指定しないとJavaのfinalクラス・メソッドになるということです。つまりKotlinのクラス・メソッドはデフォルトでは継承できません。
AndroidAnnotationsはアノテーションプロセッシングにより継承クラスを生成したりメソッドをオーバーライドしたりしますが、finalクラス・メソッドになっているとオーバーライドできないのでエラーになってしまいます。@EActivity
や@EBean
などのクラスに指定するアノテーションは全てサブクラスを生成するのでopen
を付けるようにしてください。また、@UiThread
や@Background
などのアノテーションをメソッドに付ける時も同様にopen
が必要です。@Click
や@AfterViews
などはメソッドそのものをオーバーライドするわけではないので、open
を付けなくても良いです。
@EActivity(R.layout.activity_main)
open class MainActivity : AppCompatActivity() {
@AfterViews
fun initView() {
// View初期化処理
}
@UiThread
open fun func() {
// メインスレッド処理
}
@Click
fun button() {
// android:id="@id/button" のクリック処理
}
}
フィールドアノテーションの付け方
@ViewById
や@Bean
などのアノテーションはフィールドに付けますが、Javaでこれらのアノテーションを使ったコードをKotlinに変換しただけでは、エラーになってしまいます。何故かと言うとKotlinのクラス内に宣言するvar
は実際にはフィールドの宣言ではなく、プライベートフィールドとゲッター(とセッター)の宣言に相当するものだからです。フィールドがプライベートになると生成されたサブクラスからの代入ができなくなるため、エラーになります。
このようなアノテーションを使う時は、lateinit varで宣言すると良いです。lateinit var
はコンストラクタで初期化はされないが、フレームワーク内の初期化フローの中で初期化され、実質的にnon-null型と見て問題ないプロパティを表します。@ViewById
や@Bean
などは、まさにこの用途にぴったりです。
@EActivity(R.layout.activity_main)
open class MainActivity : AppCompatActivity() {
@ViewById
lateinit var list: RecyclerView
}
ただし、複数画面対応をする場合に画面の向きに応じてレイアウト内のViewの種類が異なる場合など、@ViewById
を付けたフィールドにnull
が入る可能性がある場合はこの方法は使えません。こういう時は@JvmField
を使ってvar
でnullable型を宣言します。
@EActivity(R.layout.activity_main)
open class MainActivity : AppCompatActivity() {
@ViewById
@JvmField
var text: TextView? = null
}