LoginSignup
15
9

More than 5 years have passed since last update.

KotlinでSharedPreferenceへのアクセスを楽にするライブラリを作ってみた

Last updated at Posted at 2015-08-04

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

ReadWritePropertysetgetを持ったインターフェースになっており、値の参照時には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)に不安あり。改善していきたい。

15
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
9