kobakei's blog

プログラミングの話や技術系イベントの話をゆるく書くブログです

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に突っ込めるはずなんですが謎。 Parcelerjohncarl81/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

まだ本番投入するのは早そうです。