環境
Android Studio Arctic Fox | 2020.3.1 Patch 2
Kotlin 1.5.31
概要
列挙型の値を使うときに、@IntDef
を生かしてdata classを組み立ててみます。
なぜenumではなくIntDefを使うのか
Google I/O 19で、Build apps for the next billion users
という動画があります。
この中の、Reduce your app size
に挙げている項目で、Avoid enumerations
というものがあります。
一個のenumでファイルのサイズが 1.0~1.4 KB程度増えるとあり、使い方によってはさらに増えるそうです。
このことは、公式のドキュメントにも記載があります。
https://developer.android.com/topic/performance/reduce-apk-size#remove-enums
というわけで、Google wayとしてenumを使わずにIntDefアノテーションで対応をしてみます。
TypedefアノテーションクラスをJavaで用意する
IntDefを定義するアノテーションクラスをJavaで用意します。
@IntDef({Status.IDLE, Status.PROCESSING, Status.DONE, Status.CANCELLED})
@Retention(RetentionPolicy.SOURCE)
@interface Status {
int IDLE = 0;
int PROCESSING = 1;
int DONE = 2;
int CANCELLED = 3;
}
Kotlinで用意しようとすると、後述のアノテーションによる検査が効かなかったです。これではアノテーションの意味がないのでJavaで用意してますが、反映させる方法があったら誰か教えてください。
2022/10/23追記
以下の環境ではKotlinでもアノテーション検査が効いていることを確認しています。
Android Studio Dolphin | 2021.3.1
Build #AI-213.7172.25.2113.9014738, built on September 1, 2022
Runtime version: 11.0.13+0-b1751.21-8125866 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 12.6
GC: G1 Young Generation, G1 Old Generation
Memory: 2048M
Cores: 16
Registry:
external.system.auto.import.disabled=true
ide.text.editor.with.preview.show.floating.toolbar=false
Non-Bundled Plugins:
org.intellij.plugins.markdown (213.6777.22)
com.github.setial (4.0.2)
Dart (213.7433)
com.thoughtworks.gauge (213.5744.125)
de.ohmesoftware.parcelablegenerator (0.7.1)
io.flutter (70.2.3)
// アノテーションによる検査が効かない
@Retention(AnnotationRetention.SOURCE)
@IntDef(IDLE, PROCESSING, DONE, CANCELLED)
annotation class Status
// Declare the constants
const val IDLE = 0
const val PROCESSING = 1
const val DONE = 2
const val CANCELLED = 3
data classでIntDefな値を提供する
以下のコードのように、コンストラクタの引数には@setparam
をつけたprivate varなパラメータを用意し、別途@get
で公開用のvalなパラメータを用意します。
data class MyData(@setparam:Status private var _state: Int) {
@get:Status
val state: Int = _state
}
IntDefな値を提供するdata classを使う
全体のコード
val data = MyData(CANCELLED)
val state = data.state
val i = when(state) {
Status.CANCELLED -> {
1
}
Status.DONE -> {
2
}
Status.IDLE -> {
3
}
Status.PROCESSING -> {
4
}
else -> 5
}
print(i)
アノテーションクラスをJavaで提供していると、data classの@get
の効果で、画像のようにIntDefの定数を補完するための項目が出てきます。これを使うことでenumと同じ処理分岐が可能になります。
同様に、@setparam
の効果で、data classのコンストラクタに適当な数値を入れると補完候補に@IntDef
で定義した値が選択できます。
まとめ
enumのほうが作りやすい
つかおう!IntDef!