LoginSignup
3
6

More than 5 years have passed since last update.

Kotlin AndroidプロジェクトでAndroidAnnotationsを使う

Last updated at Posted at 2017-10-19

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

}
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6