Percelable interface
モデルをActivity間でやりとりしたり、再生成時の復元処理を書いたり、など、
Percelableというインターフェースを実装すれば、面倒みてくる。
Bundleには基本的な型以外に、Percelableを実装したインスタンスを渡すことができる。
(つまり、ActivityとFragmentに渡すことができる。)
Percelableを実装するとIntentに載せることができる。
Parcelable interfaceは2つの仮想関数を持っていてそれぞれ実装する。
CREATORというstaticメンバを実装する。
- abstract describeContents()
- abstract writeToPercel(Percel dest, int flags)
- CREATOR
abstract describeContents()
describeContents()はひとまず0を返すようにする。
0以外の応答値が必要な場合についてひとまず省略。
abstract writeToPercel(Percel dest, int flags)
writeToPercel(Percel dest, int flags)はPercelに保存するデータを列挙する。
通常クラスが持つプロパティを列挙する。
CREATOR
CREATORという名前のstaticフィールドを実装する必要がある。
Interface for classes whose instances can be written to and restored from a Parcel. Classes implementing the Parcelable interface must also have a non-null static field called CREATOR of a type that implements the Parcelable.Creator interface.
Kotlinはstaticフィールドに対応していない(companionオブジェクトが対応する)ため、
companionオブジェクトとして実装する必要がある。
Percelable.Create<T>というobject式(シングルトンオブジェクト)を継承して作る。
Kotlinから呼ぶだけなら、companionオブジェクトを用意するだけで外からstaticメンバのように扱えるけれども、
Javaから呼ぶなら、さらに@JvmFieldを付ける必要がある。
Kotlnでプロパティを書くと、Javaに変換する際にgetXXX()やsetXXX()のように
自動的にgetter/setterが付く(らしい)。
プロパティに@JvmFieldアノテーションをつけると、getXXX()/setXXX()ではなく、
直接フィールドを触るように変換される。
@JvmFieldを付けずにstaticフィールドを書こうとすると、
勝手にgetXXX()/setXXX()が付いてしまい要求を満たせなくなる。
(JVM言語っぽいところを初めて理解した図…)
実装例は以下参照。
スコープ関数,run
ここ見ながら理解。
任意の型Tの拡張関数で、そのTをレシーバとする関数Rを引数にとる。
public inline fun T.run(f: T.() -> R): R = f()
例えば、文字列”AIUEO”を小文字にする例。
val str = "AIUEO".run { toLowerCase() }
println(s) // aiueo
実装例
Kotlinの文法の基本を詰めていれば問題なし。
package com.example.ikuty.myapplication.model
import android.os.Parcel
import android.os.Parcelable
data class Article(val id: String,
val title: String,
val url: String,
val user: User) : Parcelable {
companion object {
@JvmField
val CREATOR: Parcelable.Creator = object : Parcelable.Creator {
override fun createFromParcel(source: Parcel): Article = source.run {
Article(readString(),readString(),readString(),
readParcelable(Article::class.java.classLoader))
}
override fun newArray(size: Int): Array = arrayOfNulls(size)
}
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.run {
writeString(id)
writeString(title)
writeString(url)
writeParcelable(user, flags)
}
}
}