一、SharedPreferences介绍

SharedPreferences 类提供了一个通用框架,以便您能够保存和检索原始数据类型的永久性键值对。您可以使用 SharedPreferences 来保存任何原始数据:布尔值,浮点值,整型值,长整型和字符串。此数据将跨多个用户会话永久保留(即使您的应用已终止亦如此)。

SharedPreferences 使用 xml 格式为 Android 应用提供一种永久数据存贮方式,并且使用键值对的方式来存储数据的。相对于一个 Android 应用而言,目录 / data/data/your_app_package_name/shared_prefs / 下,可以被处在同一个应用中的所有 Activity 访问。Android 提供了相关的 API 来处理这些数据而不需要程序员直接操作这些文件或者考虑数据同步的问题。

二、SharedPreferences使用

SharedPreferences 本身是一个接口,程序无法直接创建 SharedPreferences 的实例,只能通过 Context 提供的 getSharedPreferences(String name,int mode) 方法来获取 SharedPreferences 的实例,其中有两个参数:第一个参数用于指定 SharedPreferences 文件的名称(格式为 xml 文件),如果该名称的文件不存在则会创建一个。第二个参数用于指定操作的模式,如下:

  • MODE_PRIVATE:默认操作模式,只有本应用程序才可以对这个 SharedPreferences 文件进行读写。
  • MODE_WORLD_READABLE:其他应用对这个 SharedPreferences 文件只能读不能修改。
  • MODE_WORLD_WRITEABLE:这个 SharedPreferences 文件能被其他的应用读写。
  • MODE_MULTI_PROCESS:这个模式在 Android2.3 之后已经弃之不用了,可以省略。

此外还得提一下 SharedPreferences.Editor 对象的一些主要方法。

  • SharedPreferences.Editor clear(): 删 SharedPreferences 中所有的数据。
  • SharedPreferences.Editor putXxx(String key , xxx value): 向 SharedPreferences 存入指定 key 对应的数据,其中 xxx 可以是 booleant 等各种基本类型数据 。
  • SharedPreferences.Editor remove(): 删除 SharedPreferences 中指定 key 对应的数据项
  • boolean commit(): Editor 编辑完成后,使用该方法同步提交修改。
  • void apply(): Editor 编辑完成后,使用该方法异步提交修改。

简单理解:在键值对中存储私有原始数据。

适用范围:用于保存少量数据,且数据的格式非常简单,如应用程序的各种配置信息。常见案例:音乐开关,用户账户设置,用户习惯设置,简单拓展:判断程序是不是第一次运行(使安卓 app 安卓后引导界面只显示一次)。

三、SharedPreferences优化

3.1 读操作的优化

每次读取一个key对应的值都要重新对文件进行一次读的操作?显然需要尽量避免笨重的I/O操作。

因此设计者针对读操作进行了简单的优化,当SharedPreferences对象第一次通过Context.getSharedPreferences()进行初始化时,对xml文件进行一次读取,并将文件内所有内容(即所有的键值对)缓到内存的一个Map中,这样,接下来所有的读操作,只需要从这个Map中取就可以了:

final class SharedPreferencesImpl implements SharedPreferences {private final File mFile;             // 对应的xml文件private Map<String, Object> mMap;     // Map中缓存了xml文件中所有的键值对
}

虽然节省了I/O的操作,但另一个视角分析,当xml中数据量过大时,这种 内存缓存机制 是否会产生 高内存占用 的风险?

这也正是很多开发者诟病SharedPreferences的原因之一,那么,从事物的两面性上来看,高内存占用 真的是设计者的问题吗?

不尽然,因为SharedPreferences的设计初衷是数据的 轻量级存储 ,对于类似应用的简单的配置项(比如一个boolean或者int类型),即使很多也并不会对内存有过高的占用;而对于复杂的数据(比如复杂对象序列化后的字符串),开发者更应该使用类似Room这样的解决方案,而非一股脑存储到SharedPreferences中。

因此,相对于「SharedPreferences会导致内存使用过高」的说法,更倾向于更客观的进行总结:

虽然 内存缓存机制 表面上看起来好像是一种 空间换时间 的权衡,实际上规避了短时间内频繁的I/O操作对性能产生的影响,而通过良好的代码规范,也能够避免该机制可能会导致内存占用过高的副作用,所以这种设计是 值得肯定 的。

3.2 写操作的优化

针对写操作,设计者同样设计了一系列的接口,以达到优化性能的目的。

我们知道对键值对进行更新是通过mSharedPreferences.edit().putString().commit()进行操作的——edit()是什么,commit()又是什么,为什么不单纯的设计初mSharedPreferences.putString()这样的接口?

设计者希望,在复杂的业务中,有时候一次操作会导致多个键值对的更新,这时,与其多次更新文件,我们更倾向将这些更新 合并到一次写操作 中,以达到性能的优化。

因此,对于SharedPreferences的写操作,设计者抽象出了一个Editor类,不管某次操作通过若干次调用putXXX()方法,更新了几个xml中的键值对,只有调用了commit()方法,最终才会真正写入文件:

// 简单的业务,一次更新一个键值对
sharedPreferences.edit().putString().commit();// 复杂的业务,一次更新多个键值对,仍然只进行一次IO操作(文件的写入)
Editor editor = sharedPreferences.edit();
editor.putString();
editor.putBoolean().putInt();
editor.commit();   // commit()才会更新文件

了解到这一点应该明白,通过简单粗暴的封装,以达到类似SPUtils.putXXX()这种所谓代码量的节省,从而忽略了Editor.commit()的设计理念和使用场景,往往是不可取的,从设计上来讲,这甚至是一种 倒退 。

另外一个值得思考的角度是,本质上文件的I/O是一个非常重的操作,直接放在主线程中的commit()方法某些场景下会导致ANR(比如数据量过大),因此更合理的方式是应该将其放入子线程执行。

因此设计者还为Editor提供了一个apply()方法,用于异步执行文件数据的同步,并推荐开发者使用apply()而非commit()。

看起来Editor+apply()方法对写操作做了很大的优化,但更多的问题随之而来,比如子线程更新文件,必然会引发 线程安全问题;此外,apply()方法真的能够像我们预期的一样,能够避免ANR吗?答案是并不能。

SharedPreferences使用及原理相关推荐

  1. Android SharedPreferences最佳实践

    Android开发中,我们经常会用到SharedPreferences,它是一种轻量的数据存储方式,通常用来存储一些简单的配置信息.看了网络上的一些文章,感觉都不是特别满意,因此希望能结合自己的经验和 ...

  2. sharedUserId

    2019独角兽企业重金招聘Python工程师标准>>> shareUserId介绍: Android给每个APK进程分配一个单独的空间,manifest中的userid就是对应一个分 ...

  3. Android Tips - 填坑手册

    转载自汤奇V分享的Android-Tips 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的人们的帮助下,我遇到的坑都顺利地被填平了. 为了便于日后遇到同样的问题 ...

  4. Android之——手机黑名单的实现

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47089209 有了前面几篇博文作为基础(<Android之--AIDL小结& ...

  5. android 开发从入门到精通

    Android-Tips This is an awesome list of tips for android. If you are a beginner, this list will be t ...

  6. Android面试复习资料整理

    Activity巩固和复习 1. 什么是Activity 四大组件之一,通常一个用户交互界面对应一个activity.activity是Context的子类,同时实现了window.callback和 ...

  7. 2020新一波跳槽季过后,Android程序员精选,大厂(小米

    那么我们在问项目时,怎么回答才好呢?建议最好做到以下几点: 明确项目是做什么的 明确项目的价值.(为什么做这个项目,它解决了用户什么痛点,它带来什么价值?) 明确项目的功能.(这个项目涉及哪些功能?) ...

  8. Android Tips - 专业填坑手册

    Android-Tips 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的人们的帮助下,我遇到的坑都顺利地被填平了. 为了便于日后遇到同样的问题时,能免于再次搜索 ...

  9. Android sharepreference槽点及改进方案

    1 概述简介 1.1 简介 众所周知,SharedPreferences是一种轻型的Android数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息 ...

最新文章

  1. 点分治问题 ----------- HDU6881 Tree Cutting or 2020杭电多校第10场 [点分治+思维]
  2. 06-密码学基础-混合密码系统
  3. There are multiple modules with names that only differ in ca
  4. Could not initialize class com.jacob.activeX.ActiveXComponent
  5. GB28181系统设计(四)-横向扩展和纵向扩展
  6. HttpClient4.x之Post请求示例
  7. python搜索关键词自动提交_简单爬虫:调用百度接口,实现关键词搜索(python_003)...
  8. python 多线程读写文件_python多线程写入文件问题
  9. 元学习算法MAML论文详解
  10. 在Ubuntu20.04上安装ros
  11. endless admin_认识Endless OS,轻量级Linux发行版
  12. MySQL学习笔记8:权限管理、数据库备份与设计
  13. handler原子锁_spring-boot-starter-current-limiting
  14. java实现手机短信发送的功能详细代码
  15. 小程序分享,禁用分享,解除禁用分享
  16. 060616信用证点滴简结(三)--D/P即期跟单托收
  17. 龙王我当定了(一个在QQ刷龙王的脚本)
  18. 【网络蠕虫】恶意代码之计算机病毒、网络蠕虫、木马
  19. Windows 使用键盘移动窗口
  20. 我没回老家过春节的那4点原因

热门文章

  1. 简历c语言项目,C/C++:如何介绍简历中的项目?
  2. 【网络工程师】<软考中级>网络互联与互联网
  3. [计网:原理与实践] 第四章:网络互联(课后习题整理)
  4. ABAP SY-SUBRC的含义解析
  5. 华严数字体系--说说不可说
  6. 为什么用IE浏览器的人越来越少?推荐这一款桌面浏览器
  7. 错误:The Operation Couldn't be Completed
  8. Karto的后端优化与回环检测功能对比测试与分析
  9. Mysql8.0 忘记密码怎么办
  10. sql Server2005 master损坏处理