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)
}
}
}