在SharedPreferences类上包装getter和setter

时间:2018-06-12 09:39:56

标签: android kotlin sharedpreferences

我想重新使用代码并包装getter和setter,因为它们具有相同的功能。

我想每个类型都要有一个共同的功能。

我认为维护特定属性而不是使所有通用更好是因为代码更容易访问这些属性。例如:MyPrefs.instance.prefOne

SharedPreferences类,包含2个函数“相同”:

import android.content.Context
import android.content.SharedPreferences

class MyPrefs private constructor() {

    companion object {
        private const val PREF_ONE = "prefOne"
        private const val PREF_TWO = "prefTwo"

        val instance = MyPrefs()
    }

    private lateinit var prefs: SharedPreferences

    fun init(context: Context) {
        this.prefs = context.getSharedPreferences(context.applicationContext.packageName
                + "." + MyPrefs::class.java.simpleName, Context.MODE_PRIVATE)
    }

    fun clear() {
        prefs.edit().clear().apply()
    }

    var prefOne: String
        get() = prefs.getString(PREF_ONE, "")
        set(prefOne) = prefs.edit().putString(PREF_ONE, prefOne).apply()

    var prefTwo: String
        get() = prefs.getString(PREF_TWO, "")
        set(prefTwo) = prefs.edit().putString(PREF_TWO, prefTwo).apply()
}

2 个答案:

答案 0 :(得分:1)

您可以使用delegated properties很好地解决这个问题。

这是一个用于存储String首选项的非常简单的示例实现:

class PreferencesDelegate(val context: Context, val key: String, val defaultValue: String = "") {
    private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return sharedPreferences.getString(key, defaultValue)
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        sharedPreferences.edit()
                .putString(key, value)
                .apply()
    }
}

您可以通过以下方式Activity使用此功能:

class MyActivity : AppCompatActivity() {
    var pref by PreferencesDelegate(this, "key")

    fun foo() {
        pref = "test"
        println(pref)
    }
}

或者使用额外的扩展功能以获得更好的语法:

fun Activity.preference(key: String, defaultValue: String = ""): PreferencesDelegate {
    return PreferencesDelegate(this, key, defaultValue)
}

class MyActivity : AppCompatActivity() {
    var pref by preference("key")
}

有些人已经与代表们进行了同样的更好的实现。查看this博客文章,以及thisthis库。可能还有很多很多其他的。

答案 1 :(得分:0)

由于zsmb13的答案,我找到了一个优雅的解决方案。

import android.content.SharedPreferences
import kotlin.reflect.KProperty

class DelegatedPreferences<T>(val prefs: SharedPreferences, private val defaultValue: T) {

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return getPreference(property.name, defaultValue)
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        setPreference(property.name, value)
    }

    private fun getPreference(key: String, defaultValue: T): T {
        with(prefs) {
            val result: Any = when (defaultValue) {
                is Boolean -> getBoolean(key, defaultValue)
                is Int -> getInt(key, defaultValue)
                is Long -> getLong(key, defaultValue)
                is Float -> getFloat(key, defaultValue)
                is String -> getString(key, defaultValue)
                else -> throw IllegalArgumentException()
            }
            @Suppress("UNCHECKED_CAST")
            return result as T
        }
    }

    private fun setPreference(key: String, value: T) {
        with(prefs.edit()) {
            when (value) {
                is Boolean -> putBoolean(key, value)
                is Int -> putInt(key, value)
                is Long -> putLong(key, value)
                is Float -> putFloat(key, value)
                is String -> putString(key, value)
                else -> throw IllegalArgumentException()
            }.apply()
        }
    }
}

特定的偏好类现在非常简单和干净:

import android.content.Context
import android.content.SharedPreferences

class MyPrefs private constructor() {

    companion object {
        val instance = MyPrefs()
    }

    val prefs: SharedPreferences by lazy {
        val context = App.instance
        context.getSharedPreferences(context.packageName + "." + MyPrefs::class.java.simpleName, Context.MODE_PRIVATE)
    }

    fun clear() {
        prefs.edit().clear().apply()
    }

    var anyProperty: String by DelegatedPreferences(prefs, "")
}

这个电话很简单:

MyPrefs.instance.anyProperty = "Hello!"
Log.d("***", MyPrefs.instance.anyProperty) // Hello!