亞寵展、全球寵物產業風向標——亞洲寵物展覽會深度解析
1107
2022-05-29
一、SharedPreferences
不同于文件的存儲方式,如果要保存的鍵值集合相對較小,則應使用SharedReferences API。SharedReferences對象指向一個包含鍵值對的文件,并提供簡單的讀寫方法。
本文從SharedReferences開始逐步引入Preference、MMKV。
1.1 獲取SharedPreferences對象
要想使用SharedPreferences來存儲數據,首先需要獲取到SharedPreferences 對象。Android中主要提供了2種方法用于得到SharedPreferences 對象。
Context 類中的getSharedPreferences()方法
此方法接收兩個參數:
第一個參數用于指定SharedPreferences文件的名稱,如果指定的文件不存在則會創建一個,SharedPreferences文件都是存放在/data/data/
第二個參數用于指定操作模式,目前只有MODE_PRIVATE這一種模式可選,它是默認的操作模式,和直接傳入0效果是相同的,表示只有當前的應用程序才可以對這個SharedPreferences文件進行讀寫。
一、SharedPreferences
不同于文件的存儲方式,如果要保存的鍵值集合相對較小,則應使用SharedReferences API。SharedReferences對象指向一個包含鍵值對的文件,并提供簡單的讀寫方法。
本文從SharedReferences開始逐步引入Preference、MMKV。
1.1 獲取SharedPreferences對象
要想使用SharedPreferences來存儲數據,首先需要獲取到SharedPreferences 對象。Android中主要提供了2種方法用于得到SharedPreferences 對象。
Context 類中的getSharedPreferences()方法
此方法接收兩個參數:
第一個參數用于指定SharedPreferences文件的名稱,如果指定的文件不存在則會創建一個,SharedPreferences文件都是存放在/data/data/
第一個參數用于指定SharedPreferences文件的名稱,如果指定的文件不存在則會創建一個,SharedPreferences文件都是存放在/data/data/
第二個參數用于指定操作模式,目前只有MODE_PRIVATE這一種模式可選,它是默認的操作模式,和直接傳入0效果是相同的,表示只有當前的應用程序才可以對這個SharedPreferences文件進行讀寫。
第二個參數用于指定操作模式,目前只有MODE_PRIVATE這一種模式可選,它是默認的操作模式,和直接傳入0效果是相同的,表示只有當前的應用程序才可以對這個SharedPreferences文件進行讀寫。
Activity 類中的getPreferences()方法
這個方法和Context中的getSharedPreferences() 方法很相似,不過它只接收一個操作模式參數,因為使用這個方法時會自動將當前活動的類名作為SharedPreferences的文件名。
注意:自API級別17以來,已棄用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE模式。如果使用則拋出SecurityException。
這里使用的是Context 類中的getSharedPreferences()方法:
public class SPUtils { //保存在手機里面的文件名 public static final String FILE_NAME = "scc_data"; private static final SPUtils spUtils = new SPUtils(); public static SPUtils getInstance() { return spUtils; } private SPUtils() { } private SharedPreferences getSP() { return AppGlobalUtils.getApplication().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); } }
文件保存路徑:/data/data/com.scc.datastorage/shared_prefs/scc_data.xml
1.2 寫入數據
通過putInt()和putString()等方法傳遞要寫入的鍵和值。然后調用apply()或commit()保存更改。
private void putSp() { SPUtils.getInstance().put("name","Scc"); SPUtils.getInstance().put("age",20); } /** * 保存數據的方法,我們需要拿到保存數據的具體類型,然后根據類型調用不同的保存方法 * 如果僅用到String等個別類型,可單獨寫方法 */ public void put(String key, Object value) { if(MStringUtils.isNullOrEmpty(key)){ return; } SharedPreferences.Editor editor = getSP().edit(); if (value instanceof String) { editor.putString(key, (String)value); } else if (value instanceof Integer) { editor.putInt(key, (Integer) value); } else if (value instanceof Boolean) { editor.putBoolean(key, (Boolean) value); } else if (value instanceof Float) { editor.putFloat(key, (Float) value); } else if (value instanceof Long) { editor.putLong(key, (Long) value); } SharedPreferencesCompat.apply(editor); }
1.3 讀取數據
調用getInt()和getString()等方法從SharedPreference獲取數據,提供所需值的鍵,如果鍵不存在,還可以選擇返回默認值。
private void getSp() { Log.e("SP","SpString:"+SPUtils.getInstance().getString("name")); Log.e("SP","SpInt:"+SPUtils.getInstance().getInt("age")); } //獲取String類型數據 public String getString(String key) { if (MStringUtils.isNullOrEmpty(key)) { return ""; } return getSP().getString(key, ""); } //獲取Int類型數據 public Integer getInt(String key) { if (MStringUtils.isNullOrEmpty(key)) { return 0; } return getSP().getInt(key, 0); }
1.4 刪除數據
調用 remove() 方法從SharedPreference刪除數據,提供所需值的鍵。
private void removeSp() { SPUtils.getInstance().remove("name"); Log.e("SP","Remove:"+SPUtils.getInstance().getString("name")); Log.e("SP","SpInt:"+SPUtils.getInstance().getInt("age")); } //移除某個key值已經對應的值 public void remove(String key) { if (!MStringUtils.isNullOrEmpty(key)) { SharedPreferences.Editor editor = getSP().edit(); editor.remove(key); SharedPreferencesCompat.apply(editor); } }
然后咱們再看看scc_data.xml的內容:
一些簡單的鍵值對存儲可以使用SharedPreference,如登錄的賬號密碼和一些基本的用戶信息。
二、Jetpack Preferences
默認情況下,Preference使用SharedReferences保存值。SharedReferences API允許跨應用程序操作保存的文件中讀取和寫入簡單的鍵值對。Preference Library 使用私有SharedReferences實例,因此只有你的應用程序才能訪問它。
這里由于我很少使用Jetpack Preferences,所以這里就不進行介紹了感興趣的可以去官方文檔自行查看,嘿嘿嘿。
三、MMKV—基于 mmap 的高性能通用 key-value 組件
MMKV 是基于 mmap 內存映射的 key-value 組件,底層序列化/反序列化使用 protobuf 實現,性能高,穩定性強。從 2015 年中至今在微信上使用,其性能和穩定性經過了時間的驗證。已移植到 Android / macOS / Win32 / POSIX 平臺,一并開源。
git 地址
3.1 MMKV 優勢
非常高效:MMKV使用mmap與文件保持內存同步,,由操作系統負責將內存回寫到文件,不必擔心 crash 導致數據丟失。使用protobuf對數值進行編碼/解碼,充分利用Android,實現最佳性能。
多進程并發:MMKV支持進程之間的并發讀寫訪問。
易于使用的:你可以隨時使用MMKV。所有的更改都會立即保存,不需要同步,也不需要apply調用。跟SharedReferences用法類似,可直接
少數幾個文件(小):MMKV包含進程鎖、編碼/解碼幫助程序和mmap邏輯等等。很整潔。
3.2 性能對比(摘自MMKV官方)
我們將 MMKV 和 SharedPreferences、SQLite 進行對比,重復學習操作 1k 次。相關的測試代碼在。結果變成了Android/MMKV/mmkvdemo/圖表。
(測試操作機器是華為Mate 20 Pro 128G,Android 10,每組重復1k次,時間單位是ms)
單性能進程可見:MMKV上超越共享的 Preferences & SQLite,在讀取性能上也有相近或超越的表現。
多進程的性能:MMMKV 無論是在寫入性能還是在讀取性能,都遠遠超越 MultiProcessSharedPreferences & SQLite & SQLite,MMKV 在 Android 多進程 key-value 存儲組件上是不二之選。
3.3 Android 接入指南
3.3.1 引入依賴
在你項目的app_module對應的build.gradle中添加如下依賴:
dependencies { implementation 'com.tencent:mmkv:1.2.12' }
3.3.2 初始化
MMKV 的使用非常簡單,所有變更立馬生效,無需調用 sync、apply。 在 App 啟動時初始化 MMKV,設定 MMKV 的根目錄(files/mmkv/),最好在在 Application 里:
public void onCreate() { super.onCreate(); //初始化MMKV String rootDir = MMKV.initialize(this); Log.e("SP","mmkv root: " + rootDir); }
3.3.3 寫入數據
private void putMMKV() { MMKVUtils.getInstance().encode("name","mmkv-Scc"); MMKVUtils.getInstance().encode("age",40); } //保存數據的方法,我們需要拿到保存數據的具體類型,然后根據類型調用不同的保存方法 public void encode(String key, Object object) { if (object instanceof String) { mmkv.encode(key, (String) object); } else if (object instanceof Integer) { mmkv.encode(key, (Integer) object); } else if (object instanceof Boolean) { mmkv.encode(key, (Boolean) object); } else if (object instanceof Float) { mmkv.encode(key, (Float) object); } else if (object instanceof Long) { mmkv.encode(key, (Long) object); } else if (object instanceof Double) { mmkv.encode(key, (Double) object); } else if (object instanceof byte[]) { mmkv.encode(key, (byte[]) object); } else { mmkv.encode(key, object.toString()); } }
你會發現他跟上面的SharedReferences基本一致。當然MMKV存儲支持的數據類型遠遠多于SharedReferences。
3.3.4 讀取數據
private void getMMKV() { Log.e("SP","MMKVString:"+MMKVUtils.getInstance().decodeString("name")); Log.e("SP","MMKVInt:"+MMKVUtils.getInstance().decodeInt("age")); } public String decodeString(String key) { return mmkv.decodeString(key, ""); } public Integer decodeInt(String key) { return mmkv.decodeInt(key, 0); }
3.3.5 移除數據
private void removeMMKV() { MMKVUtils.getInstance().removeValueForKey("name"); Log.e("SP","Remove:"+MMKVUtils.getInstance().decodeString("name")); Log.e("SP","MMKVInt:"+MMKVUtils.getInstance().decodeInt("age")); } //移除某個key對 public void removeValueForKey(String key) { mmkv.removeValueForKey(key); } //同時移除多個key對 public void removeValuesForKeys(String[] strings) { mmkv.removeValuesForKeys(strings); } //清除所有key public void clearAll() { mmkv.clearAll(); }
3.4 macOS / Win32 / POSIX 平臺
其他平臺可前往官方文檔自行接入。
四、相關鏈接
Android 數據全方案處理
MMKV-git 地址
Jetpack Preferences
Android 數據存儲(一)-文件存儲
Android iOS
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。