当前位置: 首页 > news >正文

SharedPreference在使用过程中有什么注意点?

原文地址:https://github.com/ZhaoKaiQiang/AndroidDifficultAnalysis/blob/master/09.SharedPreference%E5%9C%A8%E4%BD%BF%E7%94%A8%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%9C%89%E4%BB%80%E4%B9%88%E6%B3%A8%E6%84%8F%E7%82%B9%EF%BC%9F.md

commit()和apply()的区别

返回值

apply()没有返回值,而commit()返回boolean表明修改是否提交成功。

操作效率

apply()是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘,。

而commit()是同步的提交到硬件磁盘。

因此,在多并发commit()的时候,会等待正在处理的commit保存到磁盘后再操作,从而降低了效率。

而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,从一定程度上提高了效率。

建议

如果对提交的结果不关心的话,建议使用apply(),如果需要确保提交成功且有后续操作的话,还是需要用commit()。

多进程表现

是为了回答这个问题。

一句话:在多进程中,如果要交换数据,不要使用SharedPreference,因为在不同版本表现不稳定,推荐使用ContentProvider替代。

在有的文章中,有提到在多进程中使用SharedPreference添加下面标志位就可以了。

MODE_MULTI_PROCESS

但是在官方文档中这样提到:

This was the legacy (but undocumented) behavior in and
   before Gingerbread (Android 2.3) and this flag is implied when targetting such releases.  
   For applications targetting SDK versions greater than Android 2.3, 
   this flag must be explicitly set if desired.

@deprecated MODE_MULTI_PROCESS does not work reliably in some versions of Android, 
and furthermore does not provide any mechanism for reconciling concurrent modifications 
across processes.  Applications should not attempt to use it.  Instead, they should use an explicit 
cross-process data management approach such as ContentProvider

简单解释下,就是这个标志位在2.3之前是默认支持的,但是在2.3之后,如果需要多进程访问的情景,就需要显示的声明出来。

现在这个标志位被废弃了,因为在某些版本上表现不稳定。我们开发者不应该尝试去使用它,因为他没有提供任何并发机制,我们应该使用一种明确支持跨进程访问的机制,比如ContentProvider。

使用细节

  • ContextImpl中有一个静态的ArrayMap变量sSharedPrefs,无论有多少个ContextImpl对象实例,系统都共享这一个sSharedPrefs的Map,应用启动以后首次使用SharePreference时创建,系统结束时才可能会被垃圾回收器回收,所以如果我们一个App中频繁的使用不同文件名的SharedPreferences很多时这个Map就会很大,也即会占用移动设备宝贵的内存空间。所以我们应用中应该尽可能少的使用不同文件名的SharedPreferences,取而代之的是合并他们,减小内存使用
  • SharedPreferences在实例化时首先会从sdcard异步读文件,然后缓存在内存中;接下来的读操作都是内存缓存操作而不是文件操作。
  • 在SharedPreferences的Editor中如果用commit()方法提交数据,其过程是先把数据更新到内存,然后在当前线程中写文件操作,提交完成返回提交状态;如果用的是apply()方法提交数据,首先也是写到内存,接着在一个新线程中异步写文件,然后没有返回值。
  • 在写操作commit时有三级锁操作,效率很低,所以当我们一次有多个修改写操作时等都批量put完了再一次提交确认,这样可以提高效率。

更多参考资料

  • SharedPreference.Editor的apply和commit方法区别
  • Android应用Preference相关及源码浅析(SharePreferences篇)
  • Android源码

相关文章:

  • Android内存优化(使用SparseArray和ArrayMap代替HashMap)
  • Android中的观察者模式简单使用
  • Android内存泄漏总结
  • Android易混淆缩写笔记
  • Android将Log写入文件
  • Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView
  • Cygwin的安装
  • Android Studio使用技巧
  • Android常用权限
  • ADB操作命令
  • Android照相机(一):调用系统相机
  • 获取RSA文件的MD5和SHA1
  • Sublime Text 3 配置
  • jQuery基础知识
  • Backbone.js简单入门范例
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Apache Zeppelin在Apache Trafodion上的可视化
  • C++入门教程(10):for 语句
  • css布局,左右固定中间自适应实现
  • gops —— Go 程序诊断分析工具
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Java 23种设计模式 之单例模式 7种实现方式
  • JAVA SE 6 GC调优笔记
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 力扣(LeetCode)965
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 三栏布局总结
  • 使用parted解决大于2T的磁盘分区
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • NLPIR智能语义技术让大数据挖掘更简单
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 容器镜像
  • ​香农与信息论三大定律
  • #{}和${}的区别?
  • #QT(智能家居界面-界面切换)
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (Git) gitignore基础使用
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (正则)提取页面里的img标签
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转)原始图像数据和PDF中的图像数据
  • .aanva
  • .net Application的目录
  • .NET Core引入性能分析引导优化