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

写在前面

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
嗯,存取值都成功了。

总结

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

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

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

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

在这里插入图片描述
二、源码解析合集
在这里插入图片描述

三、开源框架合集
在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值