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

本文介绍了如何使用Kotlin的委托机制来简化SharedPreference的使用,通过创建SharedPreferencesDelegate类,实现了属性委托,使得存取数据如同操作对象属性般简便。示例代码展示了具体实现和使用方法。
摘要由CSDN通过智能技术生成

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

写在前面

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 -> [一, 三, 二]

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

XML1
XML2
嗯,存取值都成功了。

总结

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_小马快跑_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值