本文已同步发表于我的微信大众号,搜索 代码说 即可关注,欢迎与我沟通交流。

写在前面

Kotlin 中的托付机制是一种十分灵敏的语言特性,它能够让咱们将目标的某些特点或办法托付给其他目标来处理。常见的有类托付特点托付,详细用法参见:Kotlin | 10分钟搞定by托付机制。

:本文不再详细解说托付机制是什么,假如还不了解什么是托付机制,能够点击上文中的链接学习。

本文是 by 托付机制的实践,运用托付机制来对SharedPreference(以下简称sp)进行封装,然后简化其运用,默许 sp 的存取数据方式如下:

  • SharedPreference存数据:
//取得SharedPreferences的实例 sp_name是文件名
val sp: SharedPreferences = getSharedPreferences("sp_name", Context.MODE_PRIVATE)
//取得Editor 实例
val editor: SharedPreferences.Editor = sp.edit()
//以key-value方式保存数据
editor.putString("data_key", "data")
//apply()是异步写入数据
editor.apply()
//commit()是同步写入数据 
//editor.commit()
  • SharedPreference取数据:
//取得SharedPreferences的实例
val sp = getSharedPreferences("sp_name", MODE_PRIVATE)
//经过key值获取到相应的data,假如没取到,则回来后边的默许值
val data = sp.getString("data_key", "defaultValue")

通常项目中咱们会封装成类似 SPUtil 的方式运用,但是 sp 运用起来仍是稍显麻烦,下面就运用 by 托付机制对 sp 进行更高雅的封装。

运用托付机制封装SharedPreference

/**
 * SharedPreferences托付代理
 * @param context Context
 * @param spName SP存入的XML名字
 * @param defaultValue 默许值
 * @param key 存取数据时对应的key
 */
class SharedPreferencesDelegate<T>(
    private val context: Context,
    private val spName: String,
    private val defaultValue: T,
    private val key: String? = null,
) : ReadWriteProperty<Any?, T> {
    private val sp: SharedPreferences by lazy(LazyThreadSafetyMode.NONE) {
        context.getSharedPreferences(spName, Context.MODE_PRIVATE)
    }
    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val finalKey = key ?: property.name
        return when (defaultValue) {
            is Int -> sp.getInt(finalKey, defaultValue)
            is Long -> sp.getLong(finalKey, defaultValue)
            is Float -> sp.getFloat(finalKey, defaultValue)
            is Boolean -> sp.getBoolean(finalKey, defaultValue)
            is String -> sp.getString(finalKey, defaultValue)
            is Set<*> -> sp.getStringSet(finalKey, defaultValue as? Set<String>)
            else -> throw IllegalStateException("Unsupported type")
        } as T
    }
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        val finalKey = key ?: property.name
        with(sp.edit()) {
            when (value) {
                is Int -> putInt(finalKey, value)
                is Long -> putLong(finalKey, value)
                is Float -> putFloat(finalKey, value)
                is Boolean -> putBoolean(finalKey, value)
                is String -> putString(finalKey, value)
                is Set<*> -> putStringSet(finalKey, value.map { it.toString() }.toHashSet())
                else -> throw IllegalStateException("Unsupported type")
            }
            apply()
        }
    }
}

运用它:

class CommonPreferences(context: Context) {
    companion object {
        /**
         * 经过传入不同的SP文件名来存储到不同的XML中
         */
        const val FIR_SP_NAME = "FIR_SP_NAME" //文件名1
        const val SEC_SP_NAME = "SEC_SP_NAME"//文件名2
    }
    var isShow by SharedPreferencesDelegate(context, FIR_SP_NAME, false, "key_is_show")
    //这儿没有用key值,则会默许运用特点名来作为key值
    var name by SharedPreferencesDelegate(context, FIR_SP_NAME, "")
    var age by SharedPreferencesDelegate(context, SEC_SP_NAME, 0, "key_age")
    //这儿没有用key值,则会默许运用特点名来作为key值
    var cost by SharedPreferencesDelegate(context, SEC_SP_NAME, 0.0f)
}

上述代码展示了依据不同的文件名把数据存入到不同的XML文件中,你能够依据自己的需求进行调整。在 Activity 中进行存取值:

private val spInfo = CommonPreferences(this)
//存值
spInfo.isShow = true
spInfo.name = "小马快跑"
//存值
spInfo.age = 18
spInfo.cost = 123.4f
spInfo.setString = setOf("一", "二", "三")
//取值
log("isShow -> ${spInfo.isShow}, name -> ${spInfo.name}")
log("age -> ${spInfo.age}, cost -> ${spInfo.cost},setString -> ${spInfo.setString}")

能够看到对sp 的存取值简直不要太简略,跟目标特点的存取似的,来看执行成果:

E/TTT: isShow -> true, name -> 小马快跑
E/TTT: age -> 18, cost -> 123.4,setString -> [一, 三, 二]

取值成功了,那么存值呢?看下手机对应目录下是否有存入的数据:

Kotlin | 利用by委托机制封装SharedPreference
Kotlin | 利用by委托机制封装SharedPreference
嗯,存取值都成功了。

总结

主要运用的是特点托付val/var <特点名>: <类型> by <表达式>,例如:

var isShow by SharedPreferencesDelegate(context, FIR_SP_NAME, false, "key_is_show")

经过特点代码执行到 SharedPreferencesDelegate 中的逻辑进行存取操作,不用再关怀整个的存取细节,nice

欢迎扫描下方二维码或搜索微信大众号 代码说, 关注我的微信大众号查看最新文章~

Kotlin | 利用by委托机制封装SharedPreference