(2015/08/07) 色々と追記しました。
KotlinではDelegateでプロパティへの代入/参照時の動作を委譲することができます。
これを利用して代入/参照時にプロパティ名をキーにしてSharedPreferenceに書込/読込をできるようになるかなーと思ったので試しに作ってみました。
できたもの
使い方
インストール
compile 'com.chibatching:kotpref:0.1.0'
モデルを作成
元になるモデルクラスを継承してobjectなりclassを作る。
public object UserInfo : KotprefModel() {
var name: String by stringPrefVar()
var age: Int by intPrefVar()
var highScore: Long by longPrefVar()
var threshold: Float by floatPrefVar()
var prizes: MutableSet<String> by stringSetPrefVar(default = TreeSet<String>())
}
セットアップ
コンテキストを渡してあげる
Kotpref.init(context)
Read/Write
プロパティへの代入でSharedPreferenceへの書き込み、値を参照すればSharedPreferenceから読み込み
UserInfo.name = "chibatching"
UserInfo.age = 30
UserInfo.highScore = 49219902
UserInfo.threshold = 49.21F
UserInfo.prizes.add("Bronze")
UserInfo.prizes.add("Silver")
UserInfo.prizes.add("Gold")
Log.d(javaClass.getSimpleName(), "User name: ${UserInfo.name}")
Log.d(javaClass.getSimpleName(), "User age: ${UserInfo.age}")
Log.d(javaClass.getSimpleName(), "User high score: ${UserInfo.highScore}")
Log.d(javaClass.getSimpleName(), "User threshold: ${UserInfo.threshold}")
UserInfo.prizes.forEachIndexed { i, s -> Log.d(javaClass.getSimpleName(), "prize[$i]: ${s}") }
XML
SharedPreferenceのディレクトリにモデルクラス名でXMLが作られる。今回の例だと「UserInfo.xml」になる。
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<long name="highScore" value="49219902" />
<set name="prizes">
<string>Bronze</string>
<string>Gold</string>
<string>Silver</string>
</set>
<string name="name">chibatching</string>
<int name="age" value="30" />
<float name="threshold" value="49.21" />
</map>
オプション
デフォルト値の変更
Delegateの引数default
を指定する。
var age: Int by intPrefVar(18)
または
var age: Int by intPrefVar(default = 18)
SharedPreferenceのファイル名を変更する
kotprefName
プロパティをオーバーライドする。デフォルトはモデルのクラス名。
public object UserInfo : KotprefModel() {
override val kotprefName: String = "user_info"
SharedPreferenceのモードを変更する
kotprefMode
プロパティをオーバーライドする。デフォルト値はContext.MODE_PRIVATE
。
public object UserInfo : KotprefModel() {
override val kotprefMode: Int = Context.MODE_MULTI_PROCESS
なにをやっているのか
プロパティの宣言時は次の関数を呼んでvar変数に相当するReadWriteProperty
を返しています。
protected fun stringPrefVar(default: String = "")
: ReadWriteProperty<KotprefModel, String> = StringPrefVar(default)
ReadWriteProperty
はset
とget
を持ったインターフェースになっており、値の参照時にはget
が、値の代入時にはset
が呼ばれます。
また、呼び出し時にはプロパティを持っているオブジェクトの型とプロパティのメタデータが渡されます。
これを利用して呼び出し元のオブジェクトが持っているSharedPreferenceを取得、プロパティ名で読込書込しています。
private class StringPrefVar(val default: String) : ReadWriteProperty<KotprefModel, String> {
override fun get(thisRef: KotprefModel, desc: PropertyMetadata): String {
// プロパティの名前が分かるので名前をキーにSharedPreferenceにアクセスする
// SharePreferenceのインスタンスはプロパティを持っているオブジェクトから取得
return thisRef.kotprefPreference.getString(desc.name, default)
}
override fun set(thisRef: KotprefModel, desc: PropertyMetadata, value: String) {
thisRef.kotprefPreference.edit().putString(desc.name, value).apply()
}
}
これから
パフォーマンス(特にStringSet)に不安あり。改善していきたい。