MMKV
问题
MMKV 的原理是什么?为什么比 SharedPreferences 快?
答案
核心原理
MMKV(Memory-Mapped Key-Value)是腾讯开源的高性能键值存储,核心优势来自两个技术:
MMKV vs SharedPreferences
| 特性 | SharedPreferences | MMKV |
|---|---|---|
| 文件格式 | XML 文本 | Protobuf 二进制 |
| 写入方式 | 全量序列化写入 | 增量追加 |
| IO 模型 | read/write 系统调用 | mmap 内存映射 |
| 跨进程 | ❌ | ✅ |
| 写入性能 | 慢 | 快 100 倍+ |
基本使用
// 初始化(Application.onCreate)
MMKV.initialize(this)
// 获取实例
val kv = MMKV.defaultMMKV()
// 读写操作
kv.encode("username", "John")
kv.encode("login_count", 42)
kv.encode("is_vip", true)
val name = kv.decodeString("username", "")
val count = kv.decodeInt("login_count", 0)
val vip = kv.decodeBool("is_vip", false)
跨进程使用
// 多进程模式
val kv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE)
// 进程 A 写入
kv.encode("token", "abc123")
// 进程 B 直接读取(通过 mmap 共享内存空间)
val token = kv.decodeString("token", "")
从 SP 迁移
val oldSp = getSharedPreferences("old_prefs", MODE_PRIVATE)
val kv = MMKV.defaultMMKV()
kv.importFromSharedPreferences(oldSp)
oldSp.edit().clear().apply() // 清除旧数据
选择建议
- 官方项目 / 简单配置 → DataStore(Google 官方推荐,Jetpack 生态)
- 高频读写 / 跨进程 / 性能敏感 → MMKV(性能最优)
- 遗留项目 → 优先迁移到 MMKV(API 兼容 SP,迁移成本低)
常见面试问题
Q1: mmap 为什么比传统文件 IO 快?
答案:
传统 IO:App → 系统调用 → 内核缓冲区 → 磁盘,每次 read/write 都需要用户态和内核态切换。
mmap:将文件直接映射到进程的虚拟内存空间,App 操作内存即操作文件,不需要系统调用开销。操作系统通过页面缓存管理脏页回写,崩溃时也能保证数据不丢失(内核负责回写)。
Q2: MMKV 的增量追加如何避免文件无限增长?
答案:
MMKV 写入时追加到文件末尾(同一个 key 写多次会有多条记录)。当文件中无效数据达到一定比例时,触发文件重整:遍历所有 key-value,只保留每个 key 的最新值,重新写入。这比 SP 的每次全量写入仍然高效得多。