-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
android_advance_cn
MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今在微信上使用,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS / Windows / POSIX 平台,一并开源。
MMKV 有一些高级设置,可以使得更符合你的需求。
-
MMKV 默认将日志打印到 logcat,不便于对线上问题进行定位和解决。你可以在 App 启动时接收转发 MMKV 的日志。实现
MMKVHandler
接口,添加类似下面的代码:@Override public boolean wantLogRedirecting() { return true; } @Override public void mmkvLog(MMKVLogLevel level, String file, int line, String func, String message) { String log = "<" + file + ":" + line + "::" + func + "> " + message; switch (level) { case LevelDebug: //Log.d("redirect logging MMKV", log); break; case LevelInfo: //Log.i("redirect logging MMKV", log); break; case LevelWarning: //Log.w("redirect logging MMKV", log); break; case LevelError: //Log.e("redirect logging MMKV", log); break; case LevelNone: //Log.e("redirect logging MMKV", log); break; } }
至于使用哪个客户端日志组件,我们推荐使用 xlog,同样也是开源自微信团队。
-
如果你不希望 MMKV 打印日志,你可以关掉它(虽然我们强烈不建议你这么做)。
注意:除非有非常强烈的证据表明MMKV的日志拖慢了App的速度,你不应该关掉日志。没有日志,日后万一用户有问题,将无法跟进。MMKV.setLogLevel(MMKVLogLevel.LevelNone);
-
MMKV 默认明文存储所有 key-value,依赖 Android 系统的沙盒机制保证文件加密。如果你担心信息泄露,你可以选择加密 MMKV。
String cryptKey = "My-Encrypt-Key"; MMKV kv = MMKV.mmkvWithID("MyID", MMKV.SINGLE_PROCESS_MODE, cryptKey);
-
你可以更改密钥,也可以将一个加密 MMKV 改成明文,或者反过来。
final String mmapID = "testAES_reKey1"; // an unencrypted MMKV instance MMKV kv = MMKV.mmkvWithID(mmapID, MMKV.SINGLE_PROCESS_MODE, null); // change from unencrypted to encrypted kv.reKey("Key_seq_1"); // change encryption key kv.reKey("Key_seq_2"); // change from encrypted to unencrypted kv.reKey(null);
-
MMKV 默认把文件存放在
$(FilesDir)/mmkv/
目录。你可以在 App 启动时自定义根目录:String dir = getFilesDir().getAbsolutePath() + "/mmkv_2"; String rootDir = MMKV.initialize(dir); Log.i("MMKV", "mmkv root: " + rootDir);
-
MMKV 甚至支持自定义某个文件的目录:
String relativePath = getFilesDir().getAbsolutePath() + "/mmkv_3"; MMKV kv = MMKV.mmkvWithID("testCustomDir", relativePath);
注意:官方推荐将 MMKV 文件存储在你 App 的私有路径内部,不要 存储在 external storage(也就是 SD card)。如果你一定要这样做,你应该遵循 Android 的 scoped storage 指引。
-
一些 Android 设备(API level 19)在安装/更新 APK 时可能出错, 导致 libmmkv.so 找不到。然后就会遇到
java.lang.UnsatisfiedLinkError
之类的 crash。有个开源库 ReLinker 专门解决这个问题,你可以用它来加载 MMKV:String dir = getFilesDir().getAbsolutePath() + "/mmkv"; MMKV.initialize(dir, new MMKV.LibLoader() { @Override public void loadLibrary(String libName) { ReLinker.loadLibrary(MyApplication.this, libName); } });
-
当从 MMKV 取一个
String
orbyte[]
的时候,会有一次从 native 到 JVM 的内存拷贝。如果这个值立即传递到另一个 native 库(JNI),又会有一次从 JVM 到 native 的内存拷贝。当这个值比较大的时候,整个过程会非常浪费。Native Buffer 就是为了解决这个问题。
Native Buffer 是由 native 创建的内存缓冲区,在 Java 里封装成NativeBuffer
类型,可以透明传递到另一个 native 库进行访问处理。整个过程避免了先拷内存到 JVM 又从 JVM 拷回来导致的浪费。示例代码:int sizeNeeded = kv.getValueActualSize("bytes"); NativeBuffer nativeBuffer = MMKV.createNativeBuffer(sizeNeeded); if (nativeBuffer != null) { int size = kv.writeValueToNativeBuffer("bytes", nativeBuffer); Log.i("MMKV", "size Needed = " + sizeNeeded + " written size = " + size); // pass nativeBuffer to another native library // ... // destroy when you're done MMKV.destroyNativeBuffer(nativeBuffer); }
-
在 crc 校验失败,或者文件长度不对的时候,MMKV 默认会丢弃所有数据。你可以让 MMKV 恢复数据。要注意的是修复率无法保证,而且可能修复出奇怪的 key-value。同样地也是实现
MMKVHandler
接口,添加以下代码:@Override public MMKVRecoverStrategic onMMKVCRCCheckFail(String mmapID) { return MMKVRecoverStrategic.OnErrorRecover; } @Override public MMKVRecoverStrategic onMMKVFileLengthError(String mmapID) { return MMKVRecoverStrategic.OnErrorRecover; }
-
MMKV 提供了备份和恢复接口,可用于备份数据到其他目录,并稍后恢复原有数据。
String backupRootDir = getFilesDir().getAbsolutePath() + "/mmkv_backup_3"; // backup one instance boolean ret = MMKV.backupOneToDirectory(mmapID, backupRootDir, null); // backup all instances long count = MMKV.backupAllToDirectory(backupRootDir); // restore one instance ret = MMKV.restoreOneMMKVFromDirectory(mmapID, backupRootDir, otherDir); // restore all instances count = MMKV.restoreAllFromDirectory(backupRootDir);
-
v1.3.0 起你可以升级 MMKV 到 key 自动过期特性。注意这是格式不向下兼容的升级操作。一旦升级到 key 自动过期,旧版 MMKV (<= v1.2.16) 将无法正常读写该文件。
-
全局过期. 最简单的用法是给整个文件设定统一的过期间隔。
// expire in a day mmkv.enableAutoKeyExpire(MMKV.ExpireInDay); // MMKV.ExpireInDay = 24 * 60 * 60
或者,你可以选择只升级 MMKV,但不设置全局过期间隔。这种情况下,默认每个 key 不过期。
// enable auto key expiration without global duration mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0
-
单独过期. 你可以给每个 key 设置单独的过期间隔,区分于文件的全局过期间隔。注意,你仍然需要先升级 MMKV 为 key 自动过期。
// enable auto key expiration with an hour duration mmkv.enableAutoKeyExpire(MMKV.ExpireInHour); // MMKV.ExpireInHour = 60 * 60 // set a key with the file's global expiration duration, aka MMKV.ExpireInHour mmkv.encode("key_1", "some value"); // set a special key that expires in two hours mmkv.encode("key_2", "some value", 2 * 60 * 60); // set a special key that never expires mmkv.encode("key_3", "some value", MMKV.ExpireNever);
或者,你可以选择只升级 MMKV,但不设置全局过期间隔。这种情况下,默认每个 key 不过期。
// enable auto key expiration without global duration mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0 // set a key that never expires mmkv.encode("key_1", "some value"); // set a special key that expires in an hour mmkv.encode("key_2", "some value", MMKV.ExpireInHour);
-
过期间隔的单位是秒。MMKV 预定义了一些常用间隔,方便大家使用。你也可以使用任意自定义间隔,例如一周是
7 * 24 * 60 * 60
。ExpireNever = 0; ExpireInMinute = 60; ExpireInHour = 60 * 60; ExpireInDay = 24 * 60 * 60; ExpireInMonth = 30 * 24 * 60 * 60; ExpireInYear = 365 * 30 * 24 * 60 * 60;
MMKV is published under the BSD 3-Clause license. For details check out the LICENSE.TXT.
Check out the CHANGELOG.md for details of change history.
If you are interested in contributing, check out the CONTRIBUTING.md, also join our Tencent OpenSource Plan.
To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the Code of Conduct.
Check out the FAQ first. Should there be any questions, don't hesitate to create issues.
User privacy is taken very seriously: MMKV does not obtain, collect or upload any personal information. Please refer to the MMKV SDK Personal Information Protection Rules for details.
- In English
- 中文
- In English
- 中文
- In English
- 中文
-
In English
-
中文
-
Golang