Android 数据存储-SharedPreferences or MMKV
Posted 帅次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 数据存储-SharedPreferences or MMKV相关的知识,希望对你有一定的参考价值。
一、SharedPreferences
不同于文件的存储方式,如果要保存的键值集合相对较小,则应使用SharedReferences API。SharedReferences对象指向一个包含键值对的文件,并提供简单的读写方法。
本文从SharedReferences开始逐步引入Preference、MMKV。
1.1 获取SharedPreferences对象
要想使用SharedPreferences来存储数据,首先需要获取到SharedPreferences 对象。android中主要提供了2种方法用于得到SharedPreferences 对象。
Context 类中的getSharedPreferences()方法
此方法接收两个参数:
-
第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在
/data/data/<package name>/shared_prefs/
目录下的。 -
第二个参数用于指定操作模式,目前只有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 平台,一并开源。
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());
//保存任何Parcelable的类型
public void encode(String key, Parcelable parcelable)
Log.e("mmkv","Parcelable.start"+parcelable.getClass());
boolean isTrue = mmkv.encode(key, parcelable);
Log.e("mmkv","Parcelable.end"+isTrue);
你会发现他跟上面的SharedReferences基本一致。当然MMKV存储支持的数据类型远远多于SharedReferences。 支持的数据类型
-
支持以下 Java 语言基础类型:
-
boolean、int、long、float、double、byte[]
-
-
支持以下 Java 类和容器:
-
String、Set<String>
-
任何
Parcelable
的类型
-
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.3.6 添加数据扩展
-
不同业务需要区别存储,可以单独创建自己的实例。
-
业务需要多进程访问,那么在初始化的时候加上标志位 MMKV.MULTI_PROCESS_MODE
3.4 华为手机慎用腾讯MMKV框架
问题描述:
使用MMKV替换原生SharedPreference,在某些华为手机上,配置文件会莫名其妙丢失,整个应用像重新安装一样。
那么你可以自定义文件存储路径。
默认路径:/data/data/com.scc.datastorage(你的包名)/files/mmkv
//自定义文件路径。
String dir = getFilesDir().getAbsolutePath()+"mmkv-z2";
String dirPath = MMKV.initialize(this,dir);
//mmkv源码
public static String initialize(Context context, String rootDir)
MMKVLogLevel logLevel = MMKVLogLevel.LevelInfo;
return initialize(context, rootDir, (MMKV.LibLoader)null, logLevel);
3.5 SharedPreferences 迁移
-
MMKV 提供了 importFromSharedPreferences() 函数,可以比较方便地迁移数据过来。
-
MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface,在迁移的时候只需两三行代码即可,其他 CRUD 操作代码都不用改。
private void importSharedPreferences()
//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();
3.6 macOS / Win32 / POSIX 平台
其他平台可前往官方文档自行接入。
四、相关链接
以上是关于Android 数据存储-SharedPreferences or MMKV的主要内容,如果未能解决你的问题,请参考以下文章
SharedPreferences的基本使用-----存,删,改,查