-
什么是MMKV
MMKV的github地址:https://github.com/Tencent/MMKV
-
簡(jiǎn)介
MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application. It's currently available on Android, iOS/macOS, Win32 and POSIX.
官方介紹說MMKV是一套更有效率、更小、更易使用的移動(dòng)端鍵值對(duì)存儲(chǔ)框架,目前應(yīng)用于微信App中,并且可以作為第三方框架用于Android、ios、win32和posix(Portable Operating System Interface可移植操作系統(tǒng)接口)系統(tǒng)。
-
特點(diǎn)
-
Efficient. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of Android to achieve best performance.
- Multi-Process concurrency: MMKV supports concurrent read-read and read-write access between processes.
-
Easy-to-use. You can use MMKV as you go. All changes are saved immediately, no
sync, noapplycalls needed. -
Small.
- A handful of files: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
- About 50K in binary size: MMKV adds about 50K per architecture on App size, and much less when zipped (apk).
因?yàn)槭褂玫氖莔map(一種內(nèi)存映射文件方法)去保持內(nèi)存和文件數(shù)據(jù)同步,并且使用protobuf編解碼value,所以相較于Android傳統(tǒng)的基于xml的SharedPreferences來說更有效率,并且支持多進(jìn)程并發(fā)讀寫,這也相當(dāng)于提高了效率。
相比于SP,所有的改變通過encode方法立即存入,不需要像SP調(diào)用apply存入內(nèi)存,也不需要調(diào)用commit存入文件。
MMKV只包括進(jìn)程鎖、編解碼的helper和mmap的邏輯,再?zèng)]有其他的文件,在每個(gè)App中大約占50K,編譯成apk的時(shí)候還會(huì)進(jìn)一步壓縮。
-
Efficient. MMKV uses mmap to keep memory synced with file, and protobuf to encode/decode values, making the most of Android to achieve best performance.
-
支持的類型
- 基本類型:boolean, int, long, float, double, byte[]
- Classes & Collections:
- String,Set<String>
- Any class that implements
Parcelable實(shí)現(xiàn)了Parcelable的自定義bean
-
-
使用
-
添加依賴
首先,作為第三方庫的引入,當(dāng)然是添加依賴:
dependencies { implementation 'com.tencent:mmkv-static:1.2.5' // replace "1.2.5" with any available version } -
初始化
初始化通常只在App啟動(dòng)的時(shí)候執(zhí)行一次,所以放在繼承自Application的自定義類下:
class MyApp extends Application{ public void onCreate() { super.onCreate(); String rootDir = MMKV.initialize(this); System.out.println("mmkv root: " + rootDir); //…… } }注意這里的initialize方法有很多重載方法可以用:
public static String initialize(Context context) { String root = context.getFilesDir().getAbsolutePath() + "/mmkv"; MMKVLogLevel logLevel = MMKVLogLevel.LevelInfo; return initialize(root, (MMKV.LibLoader)null, logLevel); } public static String initialize(Context context, MMKVLogLevel logLevel) { String root = context.getFilesDir().getAbsolutePath() + "/mmkv"; return initialize(root, (MMKV.LibLoader)null, logLevel); } public static String initialize(String rootDir) { MMKVLogLevel logLevel = MMKVLogLevel.LevelInfo; return initialize(rootDir, (MMKV.LibLoader)null, logLevel); } public static String initialize(String rootDir, MMKVLogLevel logLevel) { return initialize(rootDir, (MMKV.LibLoader)null, logLevel); } public static String initialize(String rootDir, MMKV.LibLoader loader) { MMKVLogLevel logLevel = MMKVLogLevel.LevelInfo; return initialize(rootDir, loader, logLevel); } public static String initialize(String rootDir, MMKV.LibLoader loader, MMKVLogLevel logLevel) { if (loader != null) { if ("StaticCpp".equals("SharedCpp")) { loader.loadLibrary("c++_shared"); } loader.loadLibrary("mmkv"); } else { if ("StaticCpp".equals("SharedCpp")) { System.loadLibrary("c++_shared"); } System.loadLibrary("mmkv"); } jniInitialize(rootDir, logLevel2Int(logLevel)); MMKV.rootDir = rootDir; return MMKV.rootDir; }最后都會(huì)回調(diào)到initialize(String rootDir, MMKV.LibLoader loader, MMKVLogLevel logLevel)這個(gè)方法。
第一個(gè)參數(shù)是MMKV保存數(shù)據(jù)文件的路徑,默認(rèn)路徑是context.getFilesDir().getAbsolutePath() + "/mmkv",你可以指定其他的合法路徑作為存放地址;
通過第二個(gè)參數(shù)可以自定義MMKV庫加載器:
public interface LibLoader { void loadLibrary(String var1); }通常我們不需要自定義,默認(rèn)使用System的loadLibrary方法去加載MMKV類庫。
第三個(gè)參數(shù)是設(shè)置MMKV輸出Log的等級(jí),默認(rèn)info等級(jí),無須多言。
經(jīng)過類庫加載,MMKV就被加載到了JVM中,jniInitialize方法是native方法,底層調(diào)用MMKV的c++方法進(jìn)行初始化邏輯。
-
存放、讀取
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")));encode方法是存儲(chǔ),第一個(gè)參數(shù)是key,第二個(gè)參數(shù)是value;
decodeXxx方法是讀取,decode后面跟著要讀取的value類型,參數(shù)是key。
-
移除、查詢
MMKV kv = MMKV.defaultMMKV(); kv.removeValueForKey("bool"); System.out.println("bool: " + kv.decodeBool("bool")); //批量刪除 kv.removeValuesForKeys(new String[]{"int", "long"}); System.out.println("allKeys: " + Arrays.toString(kv.allKeys())); //查看是否保存過某個(gè)key-value對(duì) boolean hasBool = kv.containsKey("bool"); -
模塊化
If different modules/logics need isolated storage, you can also create your own MMKV instance separately.
對(duì)于不同功能模塊還可以創(chuàng)建針對(duì)性的mmkv對(duì)象:
MMKV mmkv = MMKV.mmkvWithID("MyID"); mmkv.encode("bool", true); -
模式
MMKV mmkv = MMKV.mmkvWithID("InterProcessKV", MMKV.MULTI_PROCESS_MODE); mmkv.encode("bool", true);包括defaultMMKV方法,都可以設(shè)置是多線程模式還是單線程模式,默認(rèn)是單線程模式。
-
導(dǎo)入SP
MMKV實(shí)現(xiàn)了SharedPreferences和SharedPreferences.Editor,所以你可以使用SP的api調(diào)用,比如:
public Editor putString(String key, @Nullable String value) { this.encodeString(this.nativeHandle, key, value); return this; }可見不需要commit和apply,當(dāng)然你可以在后面加上commit或apply,但實(shí)際上沒有任何意義,因?yàn)樵趐ut方法里已經(jīng)調(diào)用了encodeXxx方法,之所以保留這些api是為了適配SP使用者的習(xí)慣。
MMKV里定義了導(dǎo)入SP的方法importFromSharedPreferences(SharedPreferences preferences):
public int importFromSharedPreferences(SharedPreferences preferences) { Map<String, ?> kvs = preferences.getAll(); if (kvs != null && kvs.size() > 0) { Iterator var3 = kvs.entrySet().iterator(); while(var3.hasNext()) { Entry<String, ?> entry = (Entry)var3.next(); String key = (String)entry.getKey(); Object value = entry.getValue(); if (key != null && value != null) { if (value instanceof Boolean) { this.encodeBool(this.nativeHandle, key, (Boolean)value); } else if (value instanceof Integer) { this.encodeInt(this.nativeHandle, key, (Integer)value); } else if (value instanceof Long) { this.encodeLong(this.nativeHandle, key, (Long)value); } else if (value instanceof Float) { this.encodeFloat(this.nativeHandle, key, (Float)value); } else if (value instanceof Double) { this.encodeDouble(this.nativeHandle, key, (Double)value); } else if (value instanceof String) { this.encodeString(this.nativeHandle, key, (String)value); } else if (value instanceof Set) { this.encode(key, (Set)value); } else { simpleLog(MMKVLogLevel.LevelError, "unknown type: " + value.getClass()); } } } return kvs.size(); } else { return 0; } }所以如果項(xiàng)目中之前有過SP的存儲(chǔ),那么只需要調(diào)用一下這個(gè)方法就會(huì)把原先SP中的數(shù)據(jù)全部設(shè)置到MMKV中。
-
-
工具類封裝
實(shí)際開發(fā)中,我們不需要每次都要從MMKV.defaultMMKV()這樣開始,所以把MMKV的調(diào)用封裝起來是一件重要的事情。
public class MySpUtils { private static MMKV mv = MMKV.defaultMMKV();; private MySpUtils() {} /** * 保存數(shù)據(jù)的方法,我們需要拿到保存數(shù)據(jù)的具體類型,然后根據(jù)類型調(diào)用不同的保存方法 */ public static void encode(String key, Object object) { if (object instanceof String) { mv.encode(key, (String) object); } else if (object instanceof Integer) { mv.encode(key, (Integer) object); } else if (object instanceof Boolean) { mv.encode(key, (Boolean) object); } else if (object instanceof Float) { mv.encode(key, (Float) object); } else if (object instanceof Long) { mv.encode(key, (Long) object); } else if (object instanceof Double) { mv.encode(key, (Double) object); } else if (object instanceof byte[] ) { mv.encode(key, (byte[]) object); } else { mv.encode(key, object.toString()); } } public static void encodeSet(String key,Set<String> sets) { mv.encode(key, sets); } public static void encodeParcelable(String key,Parcelable obj) { mv.encode(key, obj); } /** * 得到保存數(shù)據(jù)的方法,我們根據(jù)默認(rèn)值得到保存的數(shù)據(jù)的具體類型,然后調(diào)用相對(duì)于的方法獲取值 */ public static Integer decodeInt(String key) { return mv.decodeInt(key, 0); } public static Double decodeDouble(String key) { return mv.decodeDouble(key, 0.00); } public static Long decodeLong(String key) { return mv.decodeLong(key, 0L); } public static Boolean decodeBoolean(String key) { return mv.decodeBool(key, false); } public static Float decodeFloat(String key) { return mv.decodeFloat(key, 0F); } public static byte[] decodeBytes(String key) { return mv.decodeBytes(key); } public static String decodeString(String key) { return mv.decodeString(key,""); } public static Set<String> decodeStringSet(String key) { return mv.decodeStringSet(key, Collections.<String>emptySet()); } public static Parcelable decodeParcelable(String key) { return mv.decodeParcelable(key, null); } /** * 移除某個(gè)key對(duì) */ public static void removeKey(String key) { mv.removeValueForKey(key); } /** * 移除部分key */ public static void removeSomeKey(String[] keyArray) { mv.removeValuesForKeys(keyArray); } /** * 清除所有key */ public static void clearAll() { mv.clearAll(); } /** * 判斷是否含有某個(gè)key */ public static void hasKey(String key){ return mv.containsKey(key); } }也可以根據(jù)需要添加各種定制化方法來設(shè)置線程模式、mmapId等。
SharedPreferences的進(jìn)化版-MMKV
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 一、成員變量 //錯(cuò)誤恢復(fù)策略相關(guān) private static final EnumMap<MMKVRecove...
- 介紹 MMKV is an efficient, small, easy-to-use mobile key-va...
- Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
- MMKV 是騰訊于 2018 年 9 月 20 日開源的一個(gè) K-V 組件,下面是官方對(duì)它的介紹: MMKV 是基...
- 快過年了,趕在年末寫點(diǎn)技術(shù)文章,這一年好像沒有寫多少技術(shù)類文章,來年繼續(xù)努力! 言歸正傳,MMKV相對(duì)于SP有哪些...