美文网首页举一反三系列
举一反三之SharedPreferences

举一反三之SharedPreferences

作者: wp529 | 来源:发表于2020-05-12 14:47 被阅读0次

​继续沿用提出问题,然后通过寻找源码的方式来探究结果。

问题1.SharedPreferences为什么是线程安全但不是进程安全的?

SharedPreferences数据的读写是线程安全的,但不是进程安全的。单个进程的多个线程是运行在一个内存地址空间里面,多个进程分别运行在不同的内存地址空间。那么两个进程的子线程都不在一个内存地址空间,锁那些自然就限制不了,所以多个进程同时读写一个SharedPreferences可能会出现数据不一致,所以是进程不安全。

问题2:SharedPreferences在获取时的name,mode有什么作用?

name:SharedPreferences使用了一个ArrayMap来管理name与file的映射,通过name来获取对应储存数据的file。

问题2.1那么为什么要使用ArrayMap?

主要原因是ArrayMap更省内存,一般的使用场景下Android官方也更推荐用ArrayMap替代HashMap,这篇文章有详细的讲解https://www.jianshu.com/p/9663c2f77a9c,然后再以这个文件为key取出SharedPreferences映射的文件。

mode:没啥好说的,就一个private完事儿

问题3:SharedPreferences底层是用什么进行的数据存储?

使用的是xml文件

问题3.1:SharedPreferences为什么使用xml做数据存储而不用json呢?

主要是因为时代的限制。SharedPreferences可以说是伴随Android的存在就存在的东西。Android刚出的时代xml还是数据存储的主流,等到json流行后,想再将xml替换为json就要涉及到各种已有项目的兼容性问题,大家都知道覆盖安装SharedPreferences这些数据还会保留的。虽然xml解析相对复杂,体积更大。但比json仍有更好的一面,比如扩展性、对数据的描述性上,所以这可能也是官方觉得没必要替换的原因吧(所以有了官方建议SharedPreferences别存大量数据)

问题4:SharedPreferences数据存储位置?

一般是在data/data/<包名>/shared_prefs目录下。可能还会存在某个文件级加密相关的目录,DE,CE这些,是由设备制造商选择是否启用,与我们无关。

image

问题5:SharedPreferences数据存储过程是什么样的?

先使用editor,内部维护了一个HashMap(这里为什么又用HashMap了?说好的推荐ArrayMap呢,原来操作较大数据HashMap效率更高)用来持有待持久化(也就是需要存入xml文件)的数据。

问题5.1:为什么要先在内存里持有一份呢?

因为IO操作比较吃资源,先内存放一份,等到要提交的时候再一起IO到xml文件里

问题5.2:调用apply和commit都可以持久化到本地。这两个方法有什么区别吗?

commit:同步操作,也就是说执行完IO操作后才执行后续代码。我们知道IO是需要时间的,那么在写入这段时间内,又进行了修改就会导致数据不一致了。所以数据再提交到内存的时候SharedPreference会把原map拷贝一份,避免在写入数据过程中发生修改。

问题5.2.1:什么是浅拷贝、深拷贝?

浅拷贝一个对象是指对对象内的基本数据类型将值拷贝,引用类型将引用拷贝过去。深拷贝一个对象,是把这个待拷贝对象完全新建了一个对象,里面的属性引用类型的话也是新建的引用,只是把值那些都复制过去了,所以深拷贝需要自己重写,要告知程序怎么进行拷贝

接问题5.2然后将待写入的数据提交至内存,至此,这个editor的数据就固定了,然后进行写入磁盘。

问题5.2.2:由谁写入磁盘呢?

写入磁盘会创建一个消息交由handler进行处理,创建了一个持有子线程的looper的handler,进行写入,虽然消息是异步的,但会一直等待消息的执行结果

image

没等待到结果锁就不会释放,主线程来时就阻塞住了,这就是SharedPreferences会造成anr的原因

接问题5.2 apply:异步操作,并不是说可以多个线程同时进行写入,而是不必等待写入完毕才执行后续代码。可以这么理解,apply就相当于是为每一个commit都创建一个子线程。

问题6:SharedPreferences数据怎么取出的?

获取SharedPreferences时会将对应的文件加载进内存(异步加载的),将文件解析成HashMap。

问题6.1:如果文件还没加载完毕就取值会怎么样呢?

会阻塞住线程,一直等待加载文件完毕才返回值。

接问题6后续的值都从这个map里取。

问题6.2:如果对SharedPreferences进行了修改,会重新加载一次文件?

不会,见问题5数据持久化过程,数据在提交到内存的时候就会把待修改的数据同步修改到这个map里。

问题7.SharedPreferences的使用权限?

在Android系统里维护了一个ArrayMap<packageName,ArrayMap<File, SharedPreferencesImpl>>的map,所以一个应用只能使用自己包名下的SharedPreferences。

问题7.1:那相同包名,不同签名的应用,能获取到对方的SharedPreferences吗?

相同包名,不同签名的两个apk并不能同时存在。

问题7.1.1:那么双开的应用呢?

详见应用双开实现原理,所以也不会共用到一个SharedPreferences

相关文章

网友评论

    本文标题:举一反三之SharedPreferences

    本文链接:https://www.haomeiwen.com/subject/tppbnhtx.html