Android中的SharedPreferences陷阱
将保存SharedPreferences的xml文件删除了,能够彻底删除对应的SharedPreferences吗?
一次开发过程中,一个功能是需要将程序缓存清除掉,包括SharedPreferences文件。
第一次做的方式是,把相关的文件删除。但是发现有问题:程序退出后,再次进入程序仍然能够读取到应该被删除掉的SharedPreferences的值,但是DDMS查看要删除的pref文件确实都不在了。
为什么文件都不在了还能够取到值呢?
换了另一种清除SharedPreferences的方式:使用SharedPreferences.Editor的commit方法。结果证明,这样做是能够起作用的,调用后不退出程序都马上生效。
既然这样,第一个反应就是取SharedPreferences是首先内存缓存中取的。那为什么重启程序都还能去得到呢?
就进入源代码中看了一下,有几下几个地方可以了解了解:
取SharedPreferences实际上是在ContextImpl这个类中完成的。
1、context.getSharedPreferences(pref_name, mode)的流程:
A 在sSharedPrefs这个map(同步的)中以pref_name为键取SharedPreferencesImp对象sp。如果sp不为空并且对应的pref文件未被异常修改,就返回这个对象。否则进入B。
B 如果sp为空,重新生成一个SharedPreferenceImp对象并且加入到sSharedPrefs这个map中。
C 同步的:从pref文件中解析出map对象并用之替换SharedPreferenceImp对象中原有的存放pref键值对的mMap成员对象。如果pref文件解析异常导致map为null,就保持原有对象而不替换。 如果备份的pref文件(…pref_name.xml.bak)存在,就使用备份文件。
D 返回SharedPreferenceImp对象sp。
注意:sSharedPrefs在程序中是静态的:private static final HashMap sSharedPrefs = new HashMap(); 如果退出了程序但Context没有被清掉,那么下次进入程序仍然可能取到本应被删除掉的值。
2、从SharedPreference中取值getString(String key, String defValue):
从SharedPreferencesImp对象的mMap成员对象中根据key取出相应的对象v。如果取得的对象v为空,返回默认对象defValue;否则,返回对象v。
3、commit过程:
A 在内存中提交,即用要提交的map去刷新已有的mMap对象。如果map对象中某个键的值指向editer对象自身,就代表要移除这个键值对。
B 将步骤A返回的MemoryCommitResult对象加入到写入本地的队列中,写入本地文件。这一步目前是在同一个线程中做的,因为性能表现得很良好。在写入文件前,如果同名文件已经存在,则会原文件重命名为备份文件名,如果写入成功,才删除bak备份文件。
C 通知SharedPreferences的监听状态改变了。返回提交是否内存成功的状态。
4、EditorImpl内部类:
内部有一个Map成员对象mModified,用来保存将要提交的pref键值。
apply方法与commit方法的区别:前者先提交到内存中,再异步写到文件,并且不需要返回写入成功与否的状态;后者同步写入内存和文件。
5、MemoryCommitResult内部类:
用来存放Editor提交到内存的返回状态,包括是否有键值改变、将要写入文件中的map对象,写入文件成功与否等。
总结一下:要想及时并安全清除SharedPreferences一定要使用Editor去clear并commit,不要直接暴力地删除其xml文件。
将保存SharedPreferences的xml文件删除了,能够彻底删除对应的SharedPreferences吗?
一次开发过程中,一个功能是需要将程序缓存清除掉,包括SharedPreferences文件。
第一次做的方式是,把相关的文件删除。但是发现有问题:程序退出后,再次进入程序仍然能够读取到应该被删除掉的SharedPreferences的值,但是DDMS查看要删除的pref文件确实都不在了。
为什么文件都不在了还能够取到值呢?
换了另一种清除SharedPreferences的方式:使用SharedPreferences.Editor的commit方法。结果证明,这样做是能够起作用的,调用后不退出程序都马上生效。
既然这样,第一个反应就是取SharedPreferences是首先内存缓存中取的。那为什么重启程序都还能去得到呢?
就进入源代码中看了一下,有几下几个地方可以了解了解:
取SharedPreferences实际上是在ContextImpl这个类中完成的。
1、context.getSharedPreferences(pref_name, mode)的流程:
A 在sSharedPrefs这个map(同步的)中以pref_name为键取SharedPreferencesImp对象sp。如果sp不为空并且对应的pref文件未被异常修改,就返回这个对象。否则进入B。
B 如果sp为空,重新生成一个SharedPreferenceImp对象并且加入到sSharedPrefs这个map中。
C 同步的:从pref文件中解析出map对象并用之替换SharedPreferenceImp对象中原有的存放pref键值对的mMap成员对象。如果pref文件解析异常导致map为null,就保持原有对象而不替换。 如果备份的pref文件(…pref_name.xml.bak)存在,就使用备份文件。
D 返回SharedPreferenceImp对象sp。
注意:sSharedPrefs在程序中是静态的:private static final HashMap sSharedPrefs = new HashMap(); 如果退出了程序但Context没有被清掉,那么下次进入程序仍然可能取到本应被删除掉的值。
2、从SharedPreference中取值getString(String key, String defValue):
从SharedPreferencesImp对象的mMap成员对象中根据key取出相应的对象v。如果取得的对象v为空,返回默认对象defValue;否则,返回对象v。
3、commit过程:
A 在内存中提交,即用要提交的map去刷新已有的mMap对象。如果map对象中某个键的值指向editer对象自身,就代表要移除这个键值对。
B 将步骤A返回的MemoryCommitResult对象加入到写入本地的队列中,写入本地文件。这一步目前是在同一个线程中做的,因为性能表现得很良好。在写入文件前,如果同名文件已经存在,则会原文件重命名为备份文件名,如果写入成功,才删除bak备份文件。
C 通知SharedPreferences的监听状态改变了。返回提交是否内存成功的状态。
4、EditorImpl内部类:
内部有一个Map成员对象mModified,用来保存将要提交的pref键值。
apply方法与commit方法的区别:前者先提交到内存中,再异步写到文件,并且不需要返回写入成功与否的状态;后者同步写入内存和文件。
5、MemoryCommitResult内部类:
用来存放Editor提交到内存的返回状态,包括是否有键值改变、将要写入文件中的map对象,写入文件成功与否等。
总结一下:要想及时并安全清除SharedPreferences一定要使用Editor去clear并commit,不要直接暴力地删除其xml文件。
发表评论
-
ScrollView嵌套Edittext
2015-04-08 18:26 790scrollview 中加入多个控件如 edittext 后会 ... -
android 布局式跑马灯,非TextView
2015-04-07 10:51 450如题,简单的实现了跑马灯效果,把Scroll.java放入an ... -
Android圆角图片
2015-03-11 17:44 649my_wane_shape.xml 快速圆角背景边框实现, ... -
SQLite多线程读写实践及常见问题总结
2015-02-13 17:06 903基本操作的部分,大家都很熟悉了,这里根据个人切身经验,总结了一 ... -
android加速度感应
2015-01-19 10:25 14341.android测量数据 (1)android设备坐标系 ... -
MatrixCursor的使用
2015-01-19 09:49 1013ContentProvider对外共享数据的时候的query( ... -
Android 获取控件的宽高高级用法(MeasureSpec)
2015-01-15 14:23 939一个MeasureSpec封装了父 ... -
Android_GridView_GridView概述及实现水平滑动
2015-01-14 17:14 11171.GridView简介 GridView是ViewGroup ... -
Android MMS,SMS之常用Uri
2014-09-19 16:32 1291Android MMS,SMS之常用Uri Android ... -
android短彩信查询以及MMS表结构
2014-09-19 16:31 2104android短信的数据库的Uri是不公开的, 读取起来时灰常 ... -
使用Android自带DownloadManager下载文件
2014-08-19 11:04 734SDK在API Level 9中加入了DownloadMan ... -
android textview里链接点击事件,增加图片
2014-08-07 16:45 1101Android系统默认给TextView插入图片提供了三种方 ... -
android Home事件汇总
2014-07-18 11:30 965方法一:android 4.0以后无法通过更改页面的类型来 ... -
Android风格与主题(style and theme)
2014-07-16 16:35 638Android xml风格和主题文 ... -
Android中播放声音的两种方法
2014-05-30 15:09 608在Android中,音频、视 ... -
android 杀进程方法
2014-05-26 17:43 972关闭应用的方法: 1.System.exit(0); ... -
android service 生命周期
2014-04-21 16:16 739有了 Service 类我们如何启动他呢,有两种方法: ... -
解决ADB端口被占用的问题
2014-04-21 16:14 783究其源就是adb server没启动 经过分析整理如下: ... -
输入法隐藏打开
2013-12-23 14:24 768首次进入activity,如果有个edittex ... -
google经纬度互转
2013-07-11 16:34 895https://developers.google.com/ ...
相关推荐
android应用SharedPreferences_Demoandroid应用SharedPreferences_Demoandroid应用SharedPreferences_Demoandroid应用SharedPreferences_Demoandroid应用SharedPreferences_Demoandroid应用SharedPreferences_Demo...
DataStore 以异步、一致的事务方式存储数据,克服了 SharedPreferences(以下统称为SP)的 一些缺点。 DataStore 基于 Kotlin 协程和 Flow 实现,并且可以对 SP 数据进行迁移,旨在取代 SP 。 DataStore 提供了两种...
Android系统SharedPreferences进行的封装
android,SharedPreferences
Android中SharedPreferences.pdf 学习资料 复习资料 教学资源
利用SharedPreferences设置初始密码,并修改密码。详见http://blog.csdn.net/chenfengdejuanlian/article/details/46331031
Android使用SharedPreferences保存账号密码
android 使用SharedPreferences对数据存储/删除/读取/文件删除
Android中SharedPreferences知识的深入研究.pdf
Android中SharedPreferences类的定义.pdf 学习资料 复习资料 教学资源
在Android使用SharedPreferences实现自动登录
android学习SharedPreferences使用demo源代码
Android中SharedPreferences类的常用方法.pdf 学习资料 复习资料 教学资源
SharedPreferences是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能...
Android使用SharedPreferences进行数据存储,缓存ID等数据
NULL 博文链接:https://aarongo.iteye.com/blog/1914432
博客中android的SharedPreferences用法举例源代码,大家可以下载看看
Android使用SharedPreferences和SQLite数据库实现数据存储
Android 使用SharedPreferences实现数据的读写
Android中的SharedPreferences存储数据方式示例代码