Android
Kotlin
Parcelable
KotlinAndroidExtension

Kotlin Android ExtensionsのParcelableSupportを使う

More than 1 year has passed since last update.

先日Kotlin1.1.4がリリースされましたが、それと同時にAndroid ExtensionsによるParcelableサポートが発表されました。

Android Extensions plugin now includes an automatic Parcelable implementation generator.
https://blog.jetbrains.com/kotlin/2017/08/kotlin-1-1-4-is-out/

まだexperimentalな機能ですが、軽く触った感すでに十分使えそうだったので使い方を軽くまとめておきます。

KEEP: https://github.com/Kotlin/KEEP/blob/603cfefff14e1da3edd103b3f65fc0d5a13227a3/proposals/extensions/android-parcelable.md

概要

Parcelable化したいクラスに対し、アノテーションを付与することでコンパイル時にParcelableの実装に必用なコードが生成してくれます。

v1.1.4時点で以下のアノテーションとインターフェースが提供されています

  • @Parcelize
  • @RawType
  • Parceler

基本的な使い方(@Parcelize)

Parcelableを実装したクラスに@Parcelizeを付与するだけです。それだけでParcelableの実装に必用なコードが生成されます。

@Parcelize
class User(val name: String): Parcelable

現時点で@Parcelizeを付与できるクラスの条件は以下のとおりです

  • class or data classであること
  • Parcelableを実装していること
  • プライマリコンストラクタ内に定義されたプロパティがParcelに書き込み可能な型であること
  • プライマリコンストラクタ内のパラメータは全てvalorvarであること

以下のケースは、v1.1.4時点ではサポートされていません

  • objectクラス
  • @Parcelizeを利用したクラスの継承

@RawValue

Parcelableの持つプロパティの型が、シリアライズ可能かどうか不定な場合に利用します。
例えば、以下のようなクラスではTが不定なため警告が発生し、コンパイルが通らなくなります。

@Parcelize
class Range<T: Comparable>(lower: T, upper: T): Parcelable

このときTに対して@RawValueを付与することで、実質的にシリアライズ可能なインスタンスが渡されることを明示できます。

@Parcelize
class Range<T: Comparable>(lower: @RawValue T, upper: @RawValue T): Parcelable

ただし、Tの型が必ずシリアライズ可能であると保証するものではないため、不正な型のインスタンスを使えばランタイム中に例外が発生します。利用する際は注意が必用です。また、@RawValueを付与したプロパティのシリアライズにはParcel#writeValueが利用されるようです。(参考)

ちまみに、2017/08/30時点では、このアノテーションのプロポーザル(PR)はまだmasterにマージされていません。
https://github.com/Kotlin/KEEP/pull/72

Parceler

独自のCREATORを作るためのインターフェースです。 johncarl81/parcelerとは別物。

companion objectに実装することで、CREATORの処理を一部移譲できます。
あまり使う機会はない気がするので詳細は一旦省略します。
詳しく知りたい方はKEEPを読みましょう。

感想

軽く触ってみた感じ、かなり良さそうな印象を受けました。特に@RawValueのように、細かいユースケースをうまくサポートしているところが気に入っています。今開発しているプロダクトではjohncarl81/parcelerを使っていますが、Kotlinと組み合わせるといろいろツラいところがあり、今すぐにでも置き換えたいくらいです。