引言

Android 开发中,SharedPreferences 是一个非常实用的轻量级存储机制,用于保存应用的配置信息和简单的数据。然而直接操作 SharedPreferences 可能会导致代码重复和不易维护。在 Kotlin 中,我们可以利用其强大的委托属性功能对 SharedPreferences 进行封装,从而使得读写数据更为简洁、直观。

封装 Kotlin 类

import android.content.Context
import android.content.SharedPreferences
import kotlin.properties.Delegates.observable

class MyPreferences(context: Context, fileName: String = "default_prefs") {
    private val sharedPreferences: SharedPreferences =
        context.getSharedPreferences(fileName, Context.MODE_PRIVATE)

    // 封装一个可观察的委托属性
    var username: String by observable(sharedPreferences.getString("username", "")) { _, old, new ->
        if (old != new) {
            sharedPreferences.edit().putString("username", new).apply()
        }
    }

    // 同样的方式封装其他类型的数据
    var userAge: Int by observable(sharedPreferences.getInt("userAge", 0)) { _, old, new ->
        if (old != new) {
            sharedPreferences.edit().putInt("userAge", new).apply()
        }
    }

    // 其他自定义方法...
}

// 使用示例
val prefs = MyPreferences(this)
prefs.username = "JohnDoe"
println(prefs.username) // 输出已保存的用户名

基于委托属性的实现

在上述示例中,我们创建了一个名为 MyPreferences 的类,并且为每种需要持久化的数据类型封装了相应的委托属性。这里使用了 observable 委托,当属性值发生改变时,会自动将新值保存回 SharedPreferences

此外,还可以进一步优化,通过泛型和扩展函数的方式实现一个通用的 Preference 类,能够处理多种数据类型的存取,减少重复代码:

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

class Preference<T>(private val preferences: SharedPreferences,
                   private val key: String,
                   private val defaultValue: T) {

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return when (defaultValue) {
            is String -> preferences.getString(key, defaultValue) as T
            is Int -> preferences.getInt(key, defaultValue) as T
            is Boolean -> preferences.getBoolean(key, defaultValue) as T
            // ... 对其他类型进行扩展
            else -> throw IllegalArgumentException("This type can't be saved using Preferences")
        }
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        val editor = preferences.edit()
        when (value) {
            is String -> editor.putString(key, value as String?)
            is Int -> editor.putInt(key, value as Int)
            is Boolean -> editor.putBoolean(key, value as Boolean)
            // ... 对其他类型进行编辑
        }
        editor.apply()
    }
}

// 使用示例
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
var isNightMode by Preference(sharedPref, "is_night_mode", false)

拓展

   // 移除单个键值对
   editor.remove("username").apply()

   // 清除所有数据
   editor.clear().apply()