像对象一样操作SP

像对象一样操作SP

一、使用示例

1.在PreferenceManager中添加需要存进SP的字段

class PreferenceManager {

    //用户id,
    var userId: String by PreferenceProxy("")

    var age: Int by PreferenceProxy(0)

    var isMan: Boolean  by PreferenceProxy(false)

    var floatValue: Float  by PreferenceProxy(0.0f)

    var doubleValue: Double by PreferenceProxy(0.0)

    var bean: Bean  by PreferenceProxy(Bean.empty())
}

2.存值

App.preferenceManager .userId = "default userId"

3.取值

val value=App.preferenceManager .userId

二、原理

1.使用属性代理,将PreferenceManager的字段的set/get方法托管给PreferenceProxy

var bean: Bean  by PreferenceProxy(Bean.empty())

2.PreferenceProxy实现ReadWriteProperty接口,重写setValue/getValue方法

/**
 * SP的属性代理
 */
class PreferenceProxy<T>(private val default: T) : ReadWriteProperty<Any?, T> {

    companion object {
        val context: Context by lazy {
            App.instance
        }
    }

    private val prefs by lazy {
        context.getSharedPreferences("xxxx", Context.MODE_PRIVATE)
    }

    private val gson by lazy {
        Gson()
    }

    private val map by lazy {
        HashMap<String, Any?>()
    }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T = with(prefs) {
        val key = property.name
        //先取Map
        val mapValue = map[key]
        mapValue?.let {
            LogUtils.print("取Map:$key -> $it")
            return@with it as T
        }
        //Map没有,才去取SP
        when (default) {
            is Long -> {
                var it = getLong(key, default) as T
                LogUtils.print("取SP-Long:$key -> $it")
                //退出应用后,再次进来时,SP还有值,但是Map没有值了,所以需要在第一次取SP后,存到Map,以后就不用再取SP了
                map[key] = it
                return@with it
            }
            is String -> {
                var it = getString(key, default) as T
                LogUtils.print("取SP-String:$key -> $it")
                map[key] = it
                return@with it
            }
            is Float -> {
                var it = getFloat(key, default) as T
                LogUtils.print("取SP-Float:$key -> $it")
                map[key] = it
                return@with it
            }
            is Int -> {
                var it = getInt(key, default) as T
                LogUtils.print("取SP-Int:$key -> $it")
                map[key] = it
                return@with it
            }
            is Boolean -> {
                var it = getBoolean(key, default) as T
                LogUtils.print("取SP-Boolean:$key -> $it")
                map[key] = it
                return@with it
            }
            else -> {
                val jsonString = getString(key, null)
                if (jsonString != null) {
                    LogUtils.print("取SP-Object:$key -> $jsonString")
                    val clazz = ClassUtil.getClazz(default)
                    var it = gson.fromJson(jsonString, clazz) as T
                    map[key] = it
                    return@with it
                } else {
                    LogUtils.print("取默认值:$key -> $default")
                    return@with default
                }
            }
        }
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = with(prefs.edit()) {
        val key = property.name
        //先存SP
        val commit = when (value) {
            is Long -> {
                LogUtils.print("存SP-Long:$key -> $value")
                putLong(key, value)
            }
            is String -> {
                LogUtils.print("存SP-String:$key -> $value")
                putString(key, value)
            }
            is Float -> {
                LogUtils.print("存SP-Float:$key -> $value")
                putFloat(key, value)
            }
            is Int -> {
                LogUtils.print("存SP-Int:$key -> $value")
                putInt(key, value)
            }
            is Boolean -> {
                LogUtils.print("存SP-Boolean:$key -> $value")
                putBoolean(key, value)
            }
            else -> {
                var jsonString = gson.toJson(value)
                LogUtils.print("存SP-Object:$key -> $jsonString")
                putString(key, jsonString)
            }
        }.commit()
        //SP存成功了,再存Map
        if (commit) {
            LogUtils.print("存Map:$key -> $value")
            map[key] = value
        }
    }
}

之后再在自己的Application的伴生对象中,定义一个全局的静态PreferenceManager即可

val preferenceManager: PreferenceManager by lazy {
            PreferenceManager()
        }

三、特别提醒

为了防止Map和SP不一致,以后所有的SP操作,都必须通过PreferenceManager,禁止直接使用SharedPreferences!!!

推荐阅读更多精彩内容