Android 数据存储(二)-Preferences or MMKV

网友投稿 963 2022-05-29

一、SharedPreferences

不同于文件的存储方式,如果要保存的键值集合相对较小,则应使用SharedReferences API。SharedReferences对象指向一个包含键值对的文件,并提供简单的读写方法。

本文从SharedReferences开始逐步引入Preference、MMKV。

1.1 获取SharedPreferences对象

要想使用SharedPreferences来存储数据,首先需要获取到SharedPreferences 对象。Android中主要提供了2种方法用于得到SharedPreferences 对象。

Context 类中的getSharedPreferences()方法

此方法接收两个参数:

第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data//shared_prefs/目录下的。

第二个参数用于指定操作模式,目前只有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//shared_prefs/目录下的。

第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data//shared_prefs/目录下的。

第二个参数用于指定操作模式,目前只有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 数据存储(二)-Preferences or MMKV

Android 数据存储(一)-文件存储

Android iOS

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中的锁 重入锁ReentrantLock
下一篇:【Linux基础篇二】VMtools的安装、共享文件夹的设置
相关文章