关于 MMKV 你该了解哪些?
我在新项目中应用了两种sp替代方案,具体包括腾讯开发的MMKV框架和谷歌推出的DataStore解决方案。这篇文档仅限于阐述了我对KKMV框架的应用及其相关内容。
就MMKV框架这一技术而言,在其官方文档中已经进行了详实的介绍与说明。然而,在本文中我仅作为个人学习心得进行补充说明。
-
-
- 基础认知
- 使用流程
-
- 调用方式
-
- 获取实例
- 存储数据
- 读取数据
- 删除数据
-
SharedPreferences 迁移
-
开始开始,冲冲冲
基础认知
MMKV(mmap - key - value )是一款由腾讯开发的存储框架,在采用基于映射机制的键值对存储方案的基础上实现了良好的与SP平台兼容性,并显著提升了存储效率(这一部分内容尚未详尽,在未来优化阶段将做进一步完善)。
支持的数据类型
- 支持以下 Java 语言基础类型:
boolean、int、long、float、double、byte[]
- 支持以下 Java 类和容器:
String、Set<String>
- 任何实现了Parcelable的类型
使用流程
build(app)- 依赖
implementation 'com.tencent:mmkv:1.2.13'
代码解读
在应用启动时初始化 MMKV
MMKV 初始化 通常被安置在 Application 或 BaseActivity 中;然而,在 实际应用 中 大多数情况 下 都位于 Application 中。
//初始化MMKV框架
MMKV.initialize(this);
代码解读
官方示例
public void onCreate() {
super.onCreate();
String rootDir = MMKV.initialize(this);
System.out.println("mmkv root: " + rootDir);
}
代码解读
自我Demo
package com.defense.mmkv;
import android.app.Application;
import com.tencent.mmkv.MMKV;
public class MvvmApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化MMKV框架
MMKV.initialize(this);
}
}
代码解读
提酲:新人及粗心者,在MMKV进行应用初始化时,请确保将该application加入到列表文件中。
AndroidManifest 图示

AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.defense.mmkv">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".MvvmApplication"
android:theme="@style/Theme.MMKV">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MVVMActivity"/>
</application>
</manifest>
代码解读
调用方式
获取实例
MMKV kv = MMKV.defaultMMKV();
代码解读
存储数据
通过调用函数 MMKV.defaultMMKV() 获取实例后,在其中可以采用的方式是将数据以键值对的形式进行编码存储。其中需要注意的是,在此过程中无需自行转换数据类型即可完成操作。
MMKV.defaultMMKV().encode("age",29.99);
代码解读
图示

官方示例 - 存值
import com.tencent.mmkv.MMKV;
...
MMKV kv = MMKV.defaultMMKV();
kv.encode("bool", true);
System.out.println("bool: " + kv.decodeBool("bool"));
kv.encode("int", Integer.MIN_VALUE);
System.out.println("int: " + kv.decodeInt("int"));
kv.encode("long", Long.MAX_VALUE);
System.out.println("long: " + kv.decodeLong("long"));
kv.encode("float", -3.14f);
System.out.println("float: " + kv.decodeFloat("float"));
kv.encode("double", Double.MIN_VALUE);
System.out.println("double: " + kv.decodeDouble("double"));
kv.encode("string", "Hello from mmkv");
System.out.println("string: " + kv.decodeString("string"));
byte[] bytes = {'m', 'm', 'k', 'v'};
kv.encode("bytes", bytes);
System.out.println("bytes: " + new String(kv.decodeBytes("bytes")));
代码解读
兴趣与原理理解::闲暇时分查看编码源码可知,并非不进行类型转换而是框架内部自动进行了类型判断和逻辑处理。

读取数据
之后我会在补充一波MMKV的基础使用方式
有些人表示他们对于已经对SP形成习惯后特别采用了MMKV封装方案 - SpUtil
object SpUtil {
var mmkv: MMKV? = null
init {
mmkv = MMKV.defaultMMKV()
}
fun encode(key: String, value: Any?) {
when (value) {
is String -> mmkv?.encode(key, value)
is Float -> mmkv?.encode(key, value)
is Boolean -> mmkv?.encode(key, value)
is Int -> mmkv?.encode(key, value)
is Long -> mmkv?.encode(key, value)
is Double -> mmkv?.encode(key, value)
is ByteArray -> mmkv?.encode(key, value)
is Nothing -> return
}
}
fun <T : Parcelable> encode(key: String, t: T?) {
if(t ==null){
return
}
mmkv?.encode(key, t)
}
fun encode(key: String, sets: Set<String>?) {
if(sets ==null){
return
}
mmkv?.encode(key, sets)
}
fun decodeInt(key: String): Int? {
return mmkv?.decodeInt(key, 0)
}
fun decodeDouble(key: String): Double? {
return mmkv?.decodeDouble(key, 0.00)
}
fun decodeLong(key: String): Long? {
return mmkv?.decodeLong(key, 0L)
}
fun decodeBoolean(key: String): Boolean? {
return mmkv?.decodeBool(key, false)
}
fun decodeFloat(key: String): Float? {
return mmkv?.decodeFloat(key, 0F)
}
fun decodeByteArray(key: String): ByteArray? {
return mmkv?.decodeBytes(key)
}
fun decodeString(key: String): String? {
return mmkv?.decodeString(key, "")
}
fun <T : Parcelable> decodeParcelable(key: String, tClass: Class<T>): T? {
return mmkv?.decodeParcelable(key, tClass)
}
fun decodeStringSet(key: String): Set<String>? {
return mmkv?.decodeStringSet(key, Collections.emptySet())
}
fun removeKey(key: String) {
mmkv?.removeValueForKey(key)
}
fun clearAll() {
mmkv?.clearAll()
}
}
代码解读
删除数据
SharedPreferences 迁移
官方原文
- 该库支持调用importFromSharedPreferences()函数,并较为简便地将数据迁移到目标存储中。
- MMKV新增实现了两个接口PresharedPreferenceStore和PresharedPreferenceStoreEditor。在迁移过程中仅需编写两到三行代码即可完成,并无需修改其他代码块以执行其余常见的CRUD操作。
private void testImportSharedPreferences() {
//SharedPreferences preferences = getSharedPreferences("myData", MODE_PRIVATE);
MMKV preferences = MMKV.mmkvWithID("myData");
// 迁移旧数据
{
SharedPreferences old_man = getSharedPreferences("myData", MODE_PRIVATE);
preferences.importFromSharedPreferences(old_man);
old_man.edit().clear().commit();
}
// 跟以前用法一样
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("bool", true);
editor.putInt("int", Integer.MIN_VALUE);
editor.putLong("long", Long.MAX_VALUE);
editor.putFloat("float", -3.14f);
editor.putString("string", "hello, imported");
HashSet<String> set = new HashSet<String>();
set.add("W"); set.add("e"); set.add("C"); set.add("h"); set.add("a"); set.add("t");
editor.putStringSet("string-set", set);
// 无需调用 commit()
//editor.commit();
}
代码解读
