Kotlin | 利用by委托机制封装SharedPreference-灵析社区

IT大鲨鱼

本文是 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 = truespInfo.name = "小马快跑"//存值spInfo.age = 18spInfo.cost = 123.4fspInfo.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 -> [一, 三, 二]

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

嗯,存取值都成功了。

总结

主要利用的是属性委托val/var <属性名>: <类型> by <表达式>,例如:

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

通过属性代码执行到 SharedPreferencesDelegate 中的逻辑进行存取操作,不必再关心整个的存取细节,nice

阅读量:822

点赞量:0

收藏量:0