如何包装MMKV

MMKV是什么

官宣:MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今在微信上使用,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS / Windows 平台,一并开源。
从上我们了解到,微信早在2015年就用上了,用到至今,稳定性肯定没问题,这也是我们选择这个的原因之一,但据我了解到,微信还是有很多的原始SharedPreference存储文件,并没有全部使用,这也说明了,并不是所有场景都适合,适可而止。

为什么要用

看官方介绍,MMKV主要提供了和SharedPreference一样的key-value存储模式,protobuf 实现速度更块,跨平台数据可轻松迁移,支持指定文件存储路径,支持捕获打印LOG日志,支持跨进程,无需Context上下文,支持自定义加密方式。
等等吧,诸多的功能已经满足我们现有app所有的场景,集成大小多少呢(110kb)


image.png

昨天集成的一个老版本的AAR是300kb,新版本应该优化升级了,这大小还不是不错的。可以一用。

如何用

那么如何用呢,这里需要深度思考一下,由于谁都不能保证微信以后停止了该项目的维护,出现更好的替代方案,咱们畅想一下,5G来了,手机本地还需要存储吗?如果有一个网络云存储比现在更好呢,总之,我们要有个原则,任何一个引入的框架都不要在项目中直接使用,因为一旦用的地方相当多,你后期想替换那就是坠入深渊,想想都痛苦,为啥有的人总在加班,这是不是一个原因,哈哈,如果你的设计足够灵活,能兼容各种场景,是不是可以认为改个配置文件就OK了,闲话不多说,来看下,如何包装一下MMKV。
在看了MMKV的源码,我已经知道自己要怎么封装了

public class MMKV implements SharedPreferences, Editor {
.....
}

MMKV实现了原生的SharedPreferences, Editor接口,我们用的SharedPreferences就是该接口的实现,想要实现MMKV的包装,又能平滑的更换MMKV框架,我们用一个熟悉的设计模式- 装饰者模式,这个模式可以完美的解决该问题,又可以无缝使用MMKV的功能,又能扩展新的SharedPreferences实现,无缝切换,代码封装完,完全不需要修改原来的代码,坚守了我们代码设计的对修改关闭的原则。请看代码

interface JLSPInterface : SharedPreferences, SharedPreferences.Editor
class JLSharedPreference : JLSPInterface {
    //懒加载默认实现
    private val defaultSP: MMKV by lazy {
        MMKV.defaultMMKV()
    }

    private var sharedPreferences: SharedPreferences
    //装饰者的核心代码,将接口传进来,后期可以直接替换新的框架。
    constructor(sharedPreferences: SharedPreferences) {
        this.sharedPreferences = sharedPreferences
    }

    constructor() {
        this.sharedPreferences = defaultSP
    }

    companion object {
    
        @JvmStatic
        fun initWithContext(context: Context) {
            MMKV.initialize(context)
        }

        @JvmStatic
        fun initWithRootDir(rootDir: String) {
            MMKV.initialize(rootDir)
        }

        @JvmStatic
        fun defaultSp() = JLSharedPreference()

        @JvmStatic
        fun newSpWithId(spId: String) = JLSharedPreference(MMKV.mmkvWithID(spId))

        @JvmStatic
        fun newMultiProcessSp() {

        }
    }

    override fun contains(key: String?): Boolean {
        return sharedPreferences.contains(key)
    }

    override fun getBoolean(key: String?, defValue: Boolean): Boolean {
        return sharedPreferences.getBoolean(key, defValue)
    }

    override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener?) {
        return sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener)
    }

    override fun getInt(key: String?, defValue: Int): Int {
        return sharedPreferences.getInt(key, defValue)
    }

    override fun getAll(): MutableMap<String, *> {
        return mutableMapOf<String,Any>()
    }

    fun allKeys(): Array<String>{
         val mmkv = sharedPreferences as? MMKV ?: throw NullPointerException("目前只支持MMKV提供的allKeys")
         return mmkv.allKeys()?: arrayOf()
    }

    override fun edit(): SharedPreferences.Editor {
        return sharedPreferences.edit()
    }

    override fun getLong(key: String?, defValue: Long): Long {
        return sharedPreferences.getLong(key, defValue)
    }

    override fun getFloat(key: String?, defValue: Float): Float {
        return sharedPreferences.getFloat(key, defValue)
    }

    override fun getStringSet(key: String?, defValues: MutableSet<String>?): MutableSet<String>? {
        return sharedPreferences.getStringSet(key, defValues)
    }

    override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener?) {
        return sharedPreferences.registerOnSharedPreferenceChangeListener(listener)
    }

    override fun getString(key: String?, defValue: String?): String? {
        return sharedPreferences.getString(key, defValue)
    }

    override fun clear(): SharedPreferences.Editor {
        return sharedPreferences.edit().clear()
    }

    override fun putLong(key: String?, value: Long): SharedPreferences.Editor {
        return sharedPreferences.edit().putLong(key, value)
    }

    override fun putInt(key: String?, value: Int): SharedPreferences.Editor {
        return sharedPreferences.edit().putInt(key, value)
    }

    override fun remove(key: String?): SharedPreferences.Editor {
        return sharedPreferences.edit().remove(key)
    }

    override fun putBoolean(key: String?, value: Boolean): SharedPreferences.Editor {
        return sharedPreferences.edit().putBoolean(key, value)
    }

    override fun putStringSet(key: String?, values: MutableSet<String>?): SharedPreferences.Editor {
        return sharedPreferences.edit().putStringSet(key, values)
    }

    override fun commit(): Boolean {
        return sharedPreferences.edit().commit()
    }

    override fun putFloat(key: String?, value: Float): SharedPreferences.Editor {
        return sharedPreferences.edit().putFloat(key, value)
    }

    override fun apply() {
        return sharedPreferences.edit().apply()
    }

    override fun putString(key: String?, value: String?): SharedPreferences.Editor {
        return sharedPreferences.edit().putString(key, value)
    }

    fun importFromSharedPreferences(preferences: SharedPreferences): Int {
        val mmkv = sharedPreferences as? MMKV ?: throw NullPointerException("目前只支持MMKV迁移")
        return mmkv.importFromSharedPreferences(preferences)
    }
}

好了封装完毕。

总结

希望对你有帮助,后面还可以根据这个设计一个kotlin的属性委托,这样用起来就更加方便。具体怎么实现可以模仿https://www.jianshu.com/p/5e55e3ba5ca9
这是之前基于原生写的,可以参考哦。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容