杨说:Android数据存储

·  阅读 1056

目录

一、SharedPreferences
二、SQLite数据库存储
三、ContentProvider
四、File文件存储
五、网络存储

一、SharedPreferences

1.1 适用场景

适用于保存的相对较小键值对集合,SharedPreferences 对象指向包含键值对的文件,并提供读写这些键值对的简单方法。每个 SharedPreferences 文件均由框架进行管理,可以是私有文件,也可以是共享文件。

本质是基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息

1.2 注意事项

1.2.1 写操作

1、勿存储过大value
这些key和value会永远存在于内存之中,占用大量内存

第一次从sp中获取值的时候,有可能阻塞主线程(第一次在取值时,创建SharedPreferences需要加载文件,这时候如果读取数据,需要await在读取的部分,如果在主线程等待时间过长会导致ANR),使界面卡顿、掉帧,尽量提前初始化。启动优化时可事先初始化SharedPreferences

2、勿存储复杂数据
SharedPreferences通过xml存储解析,JSON或者HTML格式存放在sp里面的时候,需要转义,这样会带来很多&这种特殊符号,sp在解析碰到这个特殊符号的时候会进行特殊的处理,引发额外的字符串拼接以及函数调用开销。如果数据量大且复杂,严重时可能导频繁GC。

3、不要再多进程模式下操作sp
因为SharedPreferences不能在多进程下保证单例,如果多个进程操作可能会导致数据产生问题。

ContentProvider方案支持跨进程访问,并对所有SP操作均套上了ContentProvider进行访问。

1.2.2 读操作

1、不要乱edit和apply,尽量批量修改一次提交 edit会创建editor对象(最好做缓存),每进行一次apply就会创建线程,进行内存和磁盘的同步

2、建议apply,少用commit

1.2.3 锁性能差

SP的get操作,会锁定SharedPreferences对象,互斥其他操作。
SP的put操作,getEditor及commitToMemory会锁定SharedPreferences对象,put操作会锁定Editor对象,写入磁盘更会锁定一个写入锁。

1.3 apply和commit有什么区别

1、apply没有返回值而commit返回boolean表明修改是否提交成功
2、apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
3、apply方法不会提示任何失败的提示。 由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。

二、SQLite数据库存储

一种轻量级嵌入式数据库引擎,它的运算速度非常快,占用资源很少,常用来存储大量复杂的关系数据

2.1 了解SQLite中的事务操作吗?是如何做的

SQLite在做CRDU操作时都默认开启了事务,然后把SQL语句翻译成对应的SQLiteStatement并调用其相应的CRUD方法,此时整个操作还是在rollback journal这个临时文件上进行,只有操作顺利完成才会更新db数据库,否则会被回滚

2.2 使用SQLite做批量操作有什么好的方法吗?

使用SQLiteDatabase的beginTransaction方法开启一个事务,将批量操作SQL语句转化为SQLiteStatement并进行批量操作,结束后endTransaction()

2.3 如何删除SQLite中表的个别字段

SQLite数据库只允许增加字段而不允许修改和删除表字段,只能创建新表保留原有字段,删除原表

2.4 使用SQLite时会有哪些优化操作?

1、使用事务做批量操作
2、及时关闭Cursor,避免内存泄露
3、耗时操作异步化:数据库的操作属于本地IO耗时操作,建议放入异步线程中处理
4、ContentValues的容量调整:ContentValues内部采用HashMap来存储Key-Value数据,ContentValues初始容量为8,扩容时翻倍。因此建议对ContentValues填入的内容进行估量,设置合理的初始化容量,减少不必要的内部扩容操作
5、使用索引加快检索速度:对于查询操作量级较大、业务对查询要求较高的推荐使用索引

三、ContentProvider

有关ContentProvider基础知识,传送门杨说:ContentProvider知识点总结

四大组件之一,用于数据的存储和共享,不仅可以让不同应用程序之间进行数据共享,还可以选择只对哪一部分数据进行共享,可保证程序中的隐私数据不会有泄漏风险;

四、File文件存储

写入和读取文件的方法和 Java中实现I/O的程序一样

比较流行的是腾讯开源的MMKV

4.1 MMKV

4.1.1 MMKV原理

1、使用内存映射MMAP,将内存和文件映射在一起,操作内存就像操作文件一样。
2、应用崩溃后不会影响数据丢失
3、效率要比sp更高

4.1.1.1 Protobuf协议

protobuf 是google开源的一个序列化框架,类似xml,json,最大的特点是基于二进制,比传统的XML表示同样一段内容要短小得多。

protobuf是二进制存储格式,第一位代表的是key和value的总长度,后面是key长度->key, value长度->value

MMKV正式基于protobuf协议进行数据存储,存储方式为增量更新,也就是不需要每次修改数据都要重新将所有数据写入文件了。

4.1.2 MMKV缺陷

1、写数据时需要复制两次,用户态->内核态—>磁盘 所以过大的数据也会造成性能上的损耗

五、网络存储

主要在远程的服务器中存储相关数据,用户操作的相关数据可以同步到服务器上;

参考

1、Android官方文档
2、Android篇:2019初中级Android开发社招面试解答(上)
3、SharedPreferences使用性能优化
4、SharePreferences使用总结,优缺点(包含升级篇,深入理解,面试必读)
5、MMKV的原理与实现(一)
6、MMKV的原理与实现(二)
7、MMKV的原理与实现(三)

分类:
Android
标签: