结论
1. SharedPreferences 是线程安全的. 内部由大量 synchronized 关键字保障
2. SharedPreferences 不是进程安全的
3. 第一次 getSharedPreferences 会读取磁盘文件【开辟一个单线程池,异步读取,get/set操作前有awaitLoadedLocked操作,如果未把磁盘数据加载完毕, 所有的get/set操作,均卡住等待 】, 后续的 getSharedPreferences 会从内存缓存中获取.
4. 如果第一次调用 getSharedPreferences 时还没从磁盘加载完毕就调用 getXxx/putXxx , 则 getXxx/putXxx 操作会卡主, 直到数据从磁盘加载完毕后返回【所以主线程第一次调用,有ANR风险】
5. 所有的 getXxx 都是从内存中取的数据
6. apply 是同步回写内存【内存同步,即可通过get获取到最新数据,但不一定同步到磁盘了】, 然后把异步回写磁盘的任务放到一个单线程的队列中等待调度. 【apply 无返回值,即 void 】
7. commit 和前者一样, 只不过要等待异步磁盘任务结束后才返回【返回Boolean值,即磁盘同步结果:成功、失败】
8. MODE_MULTI_PROCESS 是在每次 getSharedPreferences 时检查磁盘上配置文件上次修改时间和文件大小, 一旦所有修改则会重新从磁盘加载文件. 所以并不能保证多进程数据的实时同步
9. 从 Android N 开始, 不再支持 MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE. 一旦指定, 会抛异常
10. 不要多进程使用, 很小几率会造成数据全部丢失, 现象是配置文件被删除
11. 不要依赖 MODE_MULTI_PROCESS. 这个标记就像 MODE_WORLD_READABLE/MODE_WORLD_WRITEABLE 未来会被废弃
12. 每次 apply / commit 都会把全部的数据一次性写入磁盘, 所以单个的配置文件不应该过大, 影响整体性能【如果保存数据比较多,那么每次更新,都会在磁盘同步全部数据,io操作,影响性能】【比如说有个100k的字符串,还有10个布尔值,那么每次更新布尔值,都要写那100k,严重影响性能】
13. 源码分析
https://juejin.im/entry/597446ed6fb9a06bac5bc630
网友评论