失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Nice 片 之 兄 dei 一起来看看 MMKV 。。。

Nice 片 之 兄 dei 一起来看看 MMKV 。。。

时间:2023-03-16 00:45:07

相关推荐

Nice 片 之 兄 dei 一起来看看 MMKV 。。。

LZ-Says:希望,你我都好。

前言

Hello,好久不见。

还记得某天,由于后台接口更新导致 App 本地数据库也要随之更新,因为之前项目着急,果断采用 SQLite,最直接导致只要后台接口更新,APP 就得更新。

而本地则采用一对一,Key - Values 对应。

那么,有没有一种更好的方案呢?

存 key 以及对应的 Json?

倒是一个可行的方案,只不过,用的时候还得解析,这个没办法了,暂时只能想到这么多。

老哥推荐使用 MMKV,那么什么是 MMKV?用它又有什么优势呢?

LZ 也不知道,一起来看~

MMKV

Oh,开搞咯~

一、 So,来看官方介绍:

MMKV——基于 mmap 的高性能通用 key-value 组件

支持的数据类型如下:

支持以下 Java 语言基础类型:

boolean、int、long、float、double、byte[]

支持以下 Java 类和容器:

String、Set

其次还提供了 SharedPreferences 迁移:

MMKV 提供了 importFromSharedPreferences() 函数,可以比较方便地迁移数据过来。

MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface,在迁移的时候只需两三行代码即可,其他 CRUD 操作代码都不用改。

接着,我们一起跟随官方文档来了解 MMKV 吧~

MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 年中至今,在 iOS 微信上使用已有近 3 年,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS 平台,一并开源。

而起源原因如下:

在微信客户端的日常运营中,时不时就会爆发特殊文字引起系统的 crash,点此查阅参考文章,文章里面设计的技术方案是在关键代码前后进行计数器的加减,通过检查计数器的异常,来发现引起闪退的异常文字。在会话列表、会话界面等有大量 cell 的地方,希望新加的计时器不会影响滑动性能;另外这些计数器还要永久存储下来——因为闪退随时可能发生。这就需要一个性能非常高的通用 key-value 存储组件,我们考察了 SharedPreferences、NSUserDefaults、SQLite 等常见组件,发现都没能满足如此苛刻的性能要求。考虑到这个防 crash 方案最主要的诉求还是实时写入,而 mmap 内存映射文件刚好满足这种需求,我们尝试通过它来实现一套 key-value 组件。

再来了解下有关MMKV 原理:

内存准备

通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操作系统负责将内存回写到文件,不必担心 crash 导致数据丢失。数据组织

数据序列化方面我们选用 protobuf 协议,pb 在性能和空间占用上都有不错的表现。写入优化

考虑到主要使用场景是频繁地进行写入更新,我们需要有增量更新的能力。我们考虑将增量 kv 对象序列化后,append 到内存末尾。空间增长

使用 append 实现增量更新带来了一个新的问题,就是不断 append 的话,文件大小会增长得不可控。我们需要在性能和空间上做个折中。

最后,我们一起来关注下有关性能问题:

贴心官方为我们将 MMKV 和 SharedPreferences、SQLite 进行对比,,重复读写操作 1k 次,如下图:

单进程性能

可见,MMKV 在写入性能上远远超越 SharedPreferences & SQLite,在读取性能上也有相近或超越的表现。(测试机器是 Pixel 2 XL 64G,Android 8.1,每组操作重复 1k 次,时间单位是 ms。)

多进程性能

可见,MMKV 无论是在写入性能还是在读取性能,都远远超越 MultiProcess & SharedPreferences & SQLite, MMKV 在 Android 多进程 key-value 存储组件上是不二之选。(测试机器是 Pixel 2 XL 64G,Android 8.1,每组操作重复 1k 次,时间单位是 ms。)

有关 MMKV 更多详情,请在文末点击链接查看即可。

二、开搞 MMKV

接下来分为俩个小部分,第一部分为快速上手,第二部分为项目实战,简单封装。

Step 1:快速上手

引入远程依赖库:

dependencies {implementation 'com.tencent:mmkv:1.0.13'}

初始化 MMKV,设置根目录:

String rootDir = MMKV.initialize(this);

而我们输出这个地址瞧一瞧:

/data/user/0/com.example.heliquan/files/mmkv

MMKV 提供一个全局的实例,可以直接使用:

MMKV mmkv = MMKV.defaultMMKV();mmkv.putBoolean("hlqBoolean", true);mmkv.putString("hlqStr", "HLQ_Struggle");mmkv.putInt("hlqInt", 666);mmkv.putFloat("hlqFloat", 1.0f);mmkv.putLong("hlqLong", 2L);Set<String> setSet=new ArraySet<>();setSet.add("1");setSet.add("2");setSet.add("3");mmkv.putStringSet("hlqSet",setSet);

取值也很 Easy,如下:

Log.e(TAG, "getBoolean:" + mmkv.getBoolean("hlqBoolean",false));Log.e(TAG, "getString:" + mmkv.getString("hlqStr",""));Log.e(TAG, "getInt:" + mmkv.getInt("hlqInt",-1));Log.e(TAG, "getFloat:" + mmkv.getFloat("hlqFloat",0f));Log.e(TAG, "getLong:" + mmkv.getLong("hlqLong",0L));Log.e(TAG, "hlqSet:" + mmkv.getStringSet("hlqSet",null));

如下是输出结果:

当然,也可以使用如下方式:

取值也可以使用如下方式:

来,我们一起简单实践一波:

// 写入数据mmkv.encode("userId",1);mmkv.encode("userName","贺利权");// 获取数据Log.e(TAG,"decodeInt:"+mmkv.decodeInt("userId"));Log.e(TAG,"decodeInt:"+mmkv.decodeString("userName"));

结果如下:

那么,如果同一个 key,再次赋值呢?会是最后一次的值么?

一起来看:

// 写入数据mmkv.encode("userId",1);// 获取数据Log.e(TAG,"修改前的值为:"+mmkv.decodeInt("userId"));mmkv.encode("userId",2);Log.e(TAG,"修改后的值为:"+mmkv.decodeInt("userId"));

输出结果为:

修改前的值为:1修改后的值为:2

So,我们可以根据此对数据进行更新,很 nice。

接着,比如说,我们想要移除某个 key 呢?

mmkv.remove("hlqSet");mmkv.removeValueForKey("userId");

有伙计说了,我想一次性移除多个呢?

mmkv.removeValuesForKeys(new String[]{"hlqSet","userId","hlqLong"});

老铁,你以为就是这些么?

有的伙计说了,我想分开存储怎么办呢?

MMKV userMMKV = MMKV.mmkvWithID("UserInfo");boolean userAge = userMMKV.encode("userAge", 22);userMMKV.encode("userName", "贺利权");userMMKV.encode("userVersion", 1.0);MMKV cacheMMKV = MMKV.mmkvWithID("CacheInfo");cacheMMKV.encode("cacheName", "V 1.0");cacheMMKV.encode("cacheLength", 666);

不,还可以一键迁移,那么什么又是一键迁移,我们继续往下看:

// 创建测试 SharePreferencesSharedPreferences sp = getSharedPreferences("userInfo.xml", MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.putInt("HLQAge", 22);editor.putString("HLQName", "贺大宝");editor.apply();// 创建将要存储MMKV spMMKV = MMKV.mmkvWithID("spMMKV");// 获取迁移 SharedPreferences 实例SharedPreferences userSP = getSharedPreferences("userInfo.xml", MODE_PRIVATE);// 迁移数据spMMKV.importFromSharedPreferences(userSP);userSP.edit().clear().commit();// 输出Log.e(TAG, spMMKV.decodeInt("HLQAge") + "");Log.e(TAG, spMMKV.decodeString("HLQName") + "");

输出:

22 贺大宝

有关 MMKV 使用介绍到此,有关其他细节各位自行移步官方文档 Study。

个人公众号

不定期发布博文,最近有点忙,感谢老铁理解,欢迎关注~

参考资料

MMKV 官方地址:/Tencent/MMKV/blob/master/readme_cn.md ;

如果觉得《Nice 片 之 兄 dei 一起来看看 MMKV 。。。》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。