Kotlin 1.1.4のParcelizeを試してみた
Kotlin 1.1.4でParcelableがサポートされたので、移行してみました。
注意:ParcelableサポートはまだExperimentalなので、仕様が変わる可能性があります。
導入
app/build.gradleに以下を追加します。
... apply plugin: 'kotlin-android-extensions' android { ... androidExtensions { experimental = true } } dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.4-3" ... }
Entity classをParcelable
を継承するようにし、@Parcelize
アノテーションを追加します。
@Parcelize data class Hoge constructor( val foo: String, val bar: String ) : Parcelable
あとはビルド時にCREATORが自動生成されます。便利ですね。
問題: Dateが使えない
プロパティにDate
があるとビルドエラーが発生しました。例えばこんな感じのクラス。
@Parcelize data class Hoge constructor( val foo: String, val bar: String, val createdAt: Date ) : Parcelable
Date
クラスはSerializable
なクラスなので、Parcelableに突っ込めるはずなんですが謎。
Parceler
(johncarl81/parcelerとは別物)というシリアライズ/デシリアライズを自分で書くためのインタフェースが提供されているので、companion objectに継承させて解決できます。
// Dateをread/writeするための拡張関数 fun Parcel.writeDate(date: Date) { writeLong(date.time) } fun Parcel.readDate(): Date { return Date(readLong()) } @Parcelize data class Hoge constructor( val foo: String, val bar: String, val createdAt: Date ) : Parcelable { companion object : Parceler<Hoge> { override fun create(parcel: Parcel): Hoge { return Hoge( parcel.readString(), parcel.readString(), parcel.readDate() ) } override fun Hoge.write(parcel: Parcel, flags: Int) { parcel.writeString(foo) parcel.writeString(bar) parcel.writeDate(createdAt) } } }
Parcelerを用意するのめんどくさいので、そのうち修正してほしいところですね。
問題: Proguard有効時にビルドエラー
Progaurdを有効にしてビルドするとビルドエラーが出ました。こちらのチケットのコメントにある設定を足すととりあえず解決できます。
-dontwarn my.package.entity.**
johncarl81/parcelerから移行してみて
johncarl81/parcelerだとEntity自体はParcelable
にはならなかったため、Bundle
に詰めるときなどは必ずParcels.wrap
でParcelableに変換してから詰めてたんですが、KotlinのParcelizeだと変換が不要なので、ActivityやFragmentでParcelableを扱うときは大分見やすくなると思います。
一方で、Parcelizeでは本来そのまま扱えるはずのDateが上手く扱えないなど、使いづらい点が残っていると感じます。この辺はまだExperimentalということで、今後改善されていくことを期待しています。
追記: Jelly Beansでインストールできなくなる模様
https://youtrack.jetbrains.com/issue/KT-20034
まだ本番投入するのは早そうです。