1.SharedPreferences简介
SharedPreferences 是Android提供的一种简单、通用的数据持久化技术,它使用名称/值对(NVP)机制来存储简单的基本值,支持基本类型,包括布尔型、字符串、多维字符串(StringSet)、浮点型、长整型、整型,一般用于存储一些配置信息,可以在会话之间持久化,并在同一个应用程序沙箱中运行的应用程序组件之间共享。
2. 源码浅析:
public interface SharedPreferences {
public interface OnSharedPreferenceChangeListener {
void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
}
public interface Editor {
Editor putString(String key, String value);
Editor putStringSet(String key, Set<String> values);
Editor putInt(String key, int value);
Editor putLong(String key, long value);
Editor putFloat(String key, float value);
Editor putBoolean(String key, boolean value);
Editor remove(String key);
Editor clear();
boolean commit();
void apply();
}
Map<String, ?> getAll();
String getString(String key, String defValue);
Set<String> getStringSet(String key, Set<String> defValues);
int getInt(String key, int defValue);
long getLong(String key, long defValue);
float getFloat(String key, float defValue);
boolean getBoolean(String key, boolean defValue);
boolean contains(String key);
Editor edit();
void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
}
首先,我们注意到SharedPreference 是一个接口,通过Editor这个内部接口来实现存储基本数据(字符串、字符串集合、整型、浮点型、长整形、布尔型)和清除、删除、提交数据,而自己则实现获得数据、查询数据、得到Editor并且监听数据更改的动作。
实现类则在SharedPreferencesImpl这个类中:
final class SharedPreferencesImpl implements SharedPreferences {
private final File mFile; //硬盘文件
private final File mBackupFile; //备份文件
private final int mMode; //文件操作模式
private Map<String, Object> mMap; // 保存数据
private boolean mLoaded = false; // 加载完的标志
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = false;
mMap = null;
startLoadFromDisk();//开始从硬盘上异步加载
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
/* 四种Mode :
* MODE_PRIVATE 私有,只能被应用程序本身访问
* MODE_APPEND 如果存在就添加在其后,不存在就创建新文件
* MODE_WORLD_READABLE 其他应用程序可以读
* MODE_WORLD_WRITEABLE <span style="font-family: Arial, Helvetica, sans-serif;"> 其他应用程序可以写 */</span>
public Editor edit() { //需要获得这个实例才能操作sharedPreferences数据。
synchronized (this) {
awaitLoadedLocked();
}
return new EditorImpl();
}
public final class EditorImpl implements Editor { //继续 EditorImpl
private final Map<String, Object> mModified = Maps.newHashMap();//缓存数据类,其后会以文件的形式存入硬盘
private boolean mClear = false;
public Editor putString(String key, String value) {
synchronized (this) {
mModified.put(key, value);//对SharedPreferences操作即是对mModified进行操作
return this;
}
}
public Editor putStringSet(String key, Set<String> values) {
synchronized (this) {
mModified.put(key,
(values == null) ? null : new HashSet<String>(values));
return this;
}
}
// ....部分省略
public Editor remove(String key) {
synchronized (this) {
mModified.put(key, this);//注意,并不是直接remove
return this;
}
}
public Editor clear() {
synchronized (this) {
mClear = true;
return this;
}
}
}
3.一些小技巧
1.获得SharedPreferences的三种方式
Context.getSharedPreferences(String name,int mode);//指定文件名
Activity.getPreferences(int mode);
PreferenceManager.getDefaultSharedPreference(Context context);
2.使用链式编程添加多个不同类型的键值对
由于edit().putInt(name,value) 等方法返回的是editor对象,因此可以使用链式编程方法~
Context.getSharedPreferences(fileName,mode).edit().putInt(name,value).putString(name,value).putBoolean(name,value).apply();
3. 可以使用Editor putStringSet(String name, Set<String> values)直接存储一个字符串集合
4.使用Secure Preferences(第三方类库)对SharedPreferences中的敏感数据进行加密
详情-》移步:点击打开链接
5. 彻底删除sharedPreference文件
由于创建sharedPreferences时会有一个备份文件,因此仅仅删除pre.xml文件并不能彻底删除,正确的姿势:
getSharedPreferences().edit().clear().apply();
6. commit()和apply()区别
1.返回值
commit() 返回boolean 用于判断是否提交成功。
apply() 返回void
2.失败提示
apply() 不会提示失败信息
3. 写入方式
commit()是同步提交到硬盘,而apply()是先同步写到内存,再异步写入硬盘。在并发提交多个commit时, 而commit需要等前一个写完再进行下一个,而apply是直接更改内存中的,再异步更改硬盘中的,因此apply()在一定程度上效率会更高。
详情可参照源码进行分析。
源码建议:
If you don't care about the return value and you're using this from your application's main thread, consider using apply instead.
在应用主线程中,如果你不考虑返回值,那么你可以考虑用apply代替commit。
源码note:
Unlike commit, which writes its preferences out to persistent storage synchronously, apply commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won’t be notified of any failures. If another editor on this SharedPreferences does a regular commit while a apply is still outstanding, the commit will block until all async commits are completed as well as the commit itself.
偶还是小白一枚,欢迎各位指正~