一、SharedPreference
1.1、使用
// 初始化一个sp
SharedPreferences sharedPreferences = context.getSharedPreferences("name_sp", MODE_PRIVATE);
// 修改key的值,有两种方法:commit和apply
sharedPreferences.edit().putBoolean("key_test", true).commit();
sharedPreferences.edit().putBoolean("key_test", true).apply();
// 读取一个key
sharedPreferences.getBoolean("key_test", false);
1.2、commit 和 apply 的区别
-
commit:直接在主线程中进行写入操作,属于同步提交,返回boolean值。容易阻塞主线程导致ANR。
-
apply:可能会导致数据丢失,将文件写入操作放到一个Runnable对象中,等待系统在工作线程中调用,属于异步提交,返回void,可能会导致数据丢失。其原理是创建一个等待锁放到QueuedlMork()中,并将真正数据持久化封装成一个任务放到异步队列中执行,任务执行结束会释放锁。而Activity onPuase,onStop以及Scrvice处理 onStop,onStartCommand等情况下,就会执行QueuedWork.waitToFinish()等待QueuedlMork()中的所有问题执行完(主线程等待所有任务)。因此apply 调用次数过多也会容易引起ANR问题。
1.3、优缺点
优点:
-
使用简单;
-
每次写入新数据之前都对现有文件做一次自动备份,这样在发生了意外出现了文件损坏之后,它们就会把备份的数据恢复过来。
缺点:
- SP 不能保证类型安全
获取数据的时候可能出现 ClassCastException 异常,因为使用相同的KEY调用
put()保存不同类型的数据时会覆盖掉之前保存的数据类型。
- SP 加载的数据会一直留在内存中
使用
getSharedPreferences()方法加载数据会将数据存储在静态的成员变量中,然后通过静态的 ArrayMap 缓存每一个 SP 文件,而每个 SP 文件内容通过 Map 缓存键值对数据,这样数据会一直留在内存中,浪费内存。
- 不支持多进程
SP不支持夸进程跨进程通信;代码里可以看到当使用多进程
MODE_MULTI_PROCESS操作的时候,会重新读取 SP 文件内容。
-
读写性能差,可能引起ANR
读取数据时候虽然加载文件也是异步加载的,不过
sp.get()方法是同步的,如果代码在它加载完成之前就去尝试读取键值对,线程就会阻塞,直到文件加载完成,此时如果在主线程操作的话,就会造成界面卡顿.写入数据时SP可以通过
apply()异步的方式来保存更改来避免 I/O 操作所导致的主线程的耗时,但当 Activity 启动和关闭的时候会等待这些异步提交完成保存之后,这就相当于把异步操作转换成同步操作了,从而会导致卡顿甚至 ANR。 当然这些操作也是为了能保证数据安全一致而为之。
二、DataStroe
2.1、优缺点
优点:
- DataStroe基于Kotlin协程实现和使用,官方主推性能,主线程读写(不管大小)数据都不卡顿。
缺点:
- 不支持多进程
暂时不支持多进程。
- 需要支持KT协程
DataStroe基于Kotlin协程实现和使用。
三、MMKV
MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。
3.1、优缺点
优点:
-
支持多进程
-
速度快
MMKV 无论是在写入性能还是在读取性能,都远远超越 MultiProcessSharedPreferences & SQLite & SQLite, MMKV 在 Android 多进程 key-value 存储组件上是不二之选。
MMKV特别适合高频的读写数据,比如微信聊天记录即时保存显示场景
缺点:
- 写入大数据速度较慢
当使用MMKV写入大的字符串数据时,相比于SP和DataStore会慢些,但是开发中基本不会写入那么大的字符串。
- 可能会丢数据
当设备突然断电关机等意外现象时,刚好数据保存在一半的情况下,此时文件就会发生损坏。这种问题是不可能避免的,MMKV 的底层机制在断电关机之类的操作系统级别的崩溃,没有做备份还原的操作,数据就会损失重置。
四、总结
-
如果你的应用支持KT协程,并且不需要多进程去存储数据,也没有高频同步写入数据场景,无疑谷歌的亲儿子DataStore是你优化考虑的对象。
-
需要多进程存储数据、并且可能会有高频同步写入数据、可以忽略那特殊情况下的数据丢失MMKV是你的不二之选。
-
至于SP的话,老的JAVA项目,没有高频同步写入数据,需要保证数据绝不丢失,忍着用吧。