http://www.cnblogs.com/devinzhou/articles/3627107.html
一、 背景 :
ShardPreferences 的使用介绍
为了提供简易化的键值对的文件存储, android 系统为我们提供了 SharedPreferences 这个玩意.
l 我们根据ContextWrapper( 实际上 Activity, Service,Application 都是 ContextWrapper 的子类) 提供的方法 getSharedPreferences(String name, int mode) 来获取 一个 SharedPreferences 的引用,
l 通过 SharedPreferences 的引用 调用 get*() 方法来获取 key 对应的指定类型的 value.
l 通过 SharedPreferences 的引用 调用 editor() 返回一个 Editor 对象, 就可以调用 put*() 存储 新的 键值对或对老的键值对进行修改, 然后调用 commit() 或 apply() 完成提交
二、 SharedPreferences 的局限:
提供了文件存储, 其api 非常简单易用, 轻轻松松搞定键值对的存储, 但轻便的背后也带来了一些问题.
SharedPreferences 的问题:
a) 常驻内存 : SharedPreferences 在被使用的时候会把文件中的全量数据加载到内存中,且 只要加载过, 整个SharedPreferences 文件一直常驻内存且不会被释放.
SharedPreferences 在加载完之后会放到 Context 的一个静态的HashMap 对象 sSharedPrefs 中保存, 且没有接口 把这个 对象从 sSharedPrefs中移除.因此 如果不从 SharedPreferences中移除这些数据, 这些数据将常驻内存.
b) 内容加载 : SharedPreferences 在被用到的时候加载数据的方式是 : 调用 new Thread() 开启一个线程, 然后用这个线程去 读取 SharedPreferences 对应的xml文件.
之前的Qzone在启动的时候会尝试打开 30 多个 SharedPreferences . 想象一下 在 应用启动的时候 有 30多个要求 磁盘 IO 的线程在运行, 程序肯定会被拖的比较慢.
c) 数据写入 : 每次SharedPreferences 文件中任何修改都是全量数据写入磁盘, 因此不建议较大的数据存入到SharedPreferences 文件中, 也不建议 对SharedPreferences文件进行频繁的修改, 因为每次调用 SharedPreferences 的 editor() 的 commit() 或 apply() 都会触发一次写 磁盘的 IO .
d) 提交方式 : 用 commit() 的方式提交 SharedPreferences 的修改会阻塞当前线程, 如果 阻塞的是 UI 线程 , 就有可能会造成卡顿. 建议 android 系统 为 2.3 以上的 都用 apply() 方式提交SharedPreferences 的修改.
三、 针对 SharedPreferences的建议
1. 一些较大的数据, 可以考虑自己写 db(sqlite) , 然后 在 内存中做 cache 控制 IO 操作的频率, , 同时也可以避免 全量的数据被加载到 内存中, 占用较大内存.
2. 整合 SharedPreferences 的文件数量, 避免过多的 SharedPreferences 文件 引起 创建过多的有 磁盘 IO 操作的线程.
è 如果 有10个 小的 SharedPreferences 文件, 每个 1kB, 那么读取的时候需要起 10 个 有 磁盘 IO 操作的线程, 进行 10 次 磁盘 IO 操作.
è 但如果有一个 SharedPreferences 文件, 其 大小为 10 kB, 文件读取时的 buff 为 16 kB, 则只需要 一个有 磁盘 IO 操作的线程, 进行 1 次 磁盘 IO 操作.
3. 尽量使用 apply() 代替 commit() 来完成 SharedPreferences 文件的更改的提交.
4. 在使用 SharedPreferences 的时候, 要注意 到 : SharedPreferences 中存储的数据 会 一直常驻 内存的.