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を引数にとる。
1 |
public inline fun <T, R> T.run(f: T.() -> R): R = f() |
例えば、文字列”AIUEO”を小文字にする例。
1 2 |
val str = "AIUEO".run { toLowerCase() } println(s) // aiueo |
実装例
Kotlinの文法の基本を詰めていれば問題なし。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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<Article> = object : Parcelable.Creator<Article> { override fun createFromParcel(source: Parcel): Article = source.run { Article(readString(),readString(),readString(), readParcelable(Article::class.java.classLoader)) } override fun newArray(size: Int): Array<Article?> = 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) } } } |