本文已同步发表于我的
微信大众号
,搜索代码说
即可关注,欢迎与我沟通交流。
写在前面
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 -> [一, 三, 二]
取值成功了,那么存值呢?看下手机对应目录下是否有存入的数据:
嗯,存取值都成功了。
总结
主要运用的是特点托付val/var <特点名>: <类型> by <表达式>
,例如:
var isShow by SharedPreferencesDelegate(context, FIR_SP_NAME, false, "key_is_show")
经过特点代码执行到 SharedPreferencesDelegate
中的逻辑进行存取操作,不用再关怀整个的存取细节,nice!
欢迎扫描下方二维码
或搜索微信大众号 代码说
, 关注我的微信大众号查看最新文章~