SharedPreferences 分析 --- 之一
来源:互联网 发布:图知科技 编辑:程序博客网 时间:2024/06/05 15:21
概述:
SharedPreferences(简称SP)是Android中很常用的数据存储方式,SP采用key-value(键值对)形式,
主要用于轻量级的数据存储, 尤其适合保存应用的配置参数, 但不建议使用SP 来存储大规模的数据, 可能会降低性能.以下分析都是基于android 6.0
SP采用xml文件格式来保存数据, 该文件所在目录位于/data/data//shared_prefs/
1, 使用
1,获取SharedPreferences对象
SharedPreferences userSettings = getSharedPreferences("settingapp",Context.MODE_PRIVATE);
2,获取Editor对象
SharedPreferences.Editor editor = userSettings.edit();
3, 存放数据
editor.putString("name","AA");editor.putString("URL","BB.com");
4, 完成提交(异步的)
editor.commit();
5,获取数据
String name = userSettings.getString("name"," default ");String url = userSettings.getString("URL","default");
6,删除数据
editor.remove("KEY");
7, 清空数据
editor.clear();
2, 获取SharedPreferences对象
获取SharedPreferences对象不止一种方法,例如在Activity.java中,可以调用getPreferences方法获取,但是建议
使用getSharedPreferences方法,其实最后getPreferences方法也是调用getSharedPreferences方法完成。其实是有Context的子类ContextImpl完成的。
ContextImpl的getSharedPreferences方法主要逻辑如下,
1, sSharedPrefs变量为空就创建sSharedPrefs
synchronized (ContextImpl.class) { if (sSharedPrefs == null) { sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>(); }
2, packagePrefs为空就创建,
final String packageName = getPackageName();ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);if (packagePrefs == null) { packagePrefs = new ArrayMap<String, SharedPreferencesImpl>(); sSharedPrefs.put(packageName, packagePrefs);}
3, SharedPreferencesImpl为空就创建该对象并返回。
sp = packagePrefs.get(name);if (sp == null) { File prefsFile = getSharedPrefsFile(name); sp = new SharedPreferencesImpl(prefsFile, mode); packagePrefs.put(name, sp); return sp;}
由此可知, sSharedPrefs 变量保存着一个进程中所有的以包名区分的packagePrefs,定义如下,
private static ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>> sSharedPrefs;
String 是包名,对应的值也是一个ArrayMap,该ArrayMap中保存着相同包名下创建的String对应的SharedPreferencesImpl对象。
因此,返回的是SharedPreferencesImpl对象, SharedPreferences只是一个接口, SharedPreferencesImpl实现了这个接口。
并且在构造SharedPreferencesImpl对象之前,首先调用getSharedPrefsFile方法构造对应的xml文件。
getSharedPrefsFile方法如下,
public File getSharedPrefsFile(String name) { return makeFilename(getPreferencesDir(), name + ".xml");}
getPreferencesDir方法如下,
private File getPreferencesDir() { synchronized (mSync) { if (mPreferencesDir == null) { mPreferencesDir = new File(getDataDirFile(), "shared_prefs"); } return mPreferencesDir; }}
makeFilename方法如下,
if (name.indexOf(File.separatorChar) < 0) { return new File(base, name);}
先从mSharedPrefsPaths查询是否存在相应文件;
如果文件不存在, 则创建新的xml文件; 如果目录也不存在, 则先创建目录创建目录/data/data/package name/shared_prefs/
其中mSharedPrefsPaths用于记录所有的SP文件, 是以文件名为key的Map数据结构.
SharedPreferencesImpl构造方法如下,
mFile = file; //创建为.bak为后缀的备份文件 mBackupFile = makeBackupFile(file); mMode = mode; mLoaded = false; mMap = null; startLoadFromDisk();
同名的.bak备份文件用于发生异常时, 可通过备份文件来恢复数据.
startLoadFromDisk方法如下,
new Thread("SharedPreferencesImpl-load") { public void run() { synchronized (SharedPreferencesImpl.this) { loadFromDiskLocked(); } }}.start();
mLoaded用于标记SP文件已加载到内存. 创建线程调用loadFromDiskLocked方法完成从磁盘加载sp文件的工作.
startLoadFromDisk主要逻辑如下,
1,构造Map对象,以及相关输入流
Map map = null;StructStat stat = null;try { stat = Os.stat(mFile.getPath()); if (mFile.canRead()) { BufferedInputStream str = null; try { str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);map = XmlUtils.readMapXml(str);
2,为相关变量赋值,这些完成之后,才释放线程锁,才可以执行其他方法,
mLoaded = true;//将mLoaded 赋值if (map != null) { mMap = map; mStatTimestamp = stat.st_mtime; mStatSize = stat.st_size;} else { mMap = new HashMap<String, Object>();}notifyAll();
3, edit方法
SharedPreferencesImpl的edit方法如下,
synchronized (this) { awaitLoadedLocked();}return new EditorImpl();
awaitLoadedLocked方法如下,
if (!mLoaded) { BlockGuard.getThreadPolicy().onReadFromDisk();} while (!mLoaded) { try { wait();//当没有加载完成,则进入等待状态 } catch (InterruptedException unused) { }}
EditorImpl 是SharedPreferencesImpl的内部类,实现了Editor接口,定义如下,
public final class EditorImpl implements Editor {
4,数据操作
数据操作主要是调用EditorImpl对象的方法,有2个变量,
private final Map<String, Object> mModified = Maps.newHashMap();private boolean mClear = false;
mModified 主要是缓存数据, mClear 判断是否清零。
例如,常用的putString方法如下,
public Editor putString(String key, @Nullable String value) { synchronized (this) { mModified.put(key, value); return this; }}
其他保存数据方法如下,
public Editor putStringSet(String key, @Nullable Set<String> values) { synchronized (this) { mModified.put(key, (values == null) ? null : new HashSet<String>(values)); return this; }}public Editor putInt(String key, int value) { synchronized (this) { mModified.put(key, value); return this; }}•••
由此可见,一般只能保存基本的类型的数据和Set 集合。
删除数据的remove方法如下,
public Editor remove(String key) { synchronized (this) { mModified.put(key, this); return this; }}
清除数据的clear方法如下,
public Editor clear() { synchronized (this) { mClear = true; return this; }}
- SharedPreferences 分析 --- 之一
- android api16分析 SharedPreferences
- SharedPreferences 源码分析
- Android SharedPreferences源码分析
- #SharedPreferences 工具类分析
- Android SharedPreferences 分析
- 源码分析:SharedPreferences实现
- SharedPreferences 分析 --- 之二
- 三大存储方式之一:SharedPreferences 存储
- Android中数据存储之一------SharedPreferences
- android数据存储方式之一 Sharedpreferences
- android的四大存储之一 SharedPreferences
- SharedPreferences存储类效率分析
- SharedPreferences存储类效率分析
- android api分析17 SharedPreferences
- Android源码分析之SharedPreferences
- Android源码分析之SharedPreferences
- Android SharedPreferences的使用分析
- php数组的常用函数
- css样式中空白边的合并
- centos安装图形界面
- QtPlayer——基于FFmpeg的Qt音视频播放器
- 多路访问控制(MAC)协议
- SharedPreferences 分析 --- 之一
- 树的表现形式
- HDU-2012(素数判定)
- 今日头条实现3秒切换文字信息(HttpConnection请求),再用HttpClient请求数据展示在ListView上
- Java面向对象四大特性之封装
- Bear and Three Musketeers CodeForces
- html中<input>的pattern属性
- Java语言中单例模式的四种写法
- linux常用命令