Sharedpreferences 内部工作原理:
- 调用getSharedPreferences(); 创建一个SharedPreferences对象,其中会先判断是否存在对应xml文件,如果发现存在则会有一个预加载操作,这个操作是把xml文件的内容通过I/O操作和XmlUitl 解析后存入一个map对象,所以我们调用SharedPreferences::getString();等get操作实际上是不会对文件做I/O操作,而是直接访问刚刚的map集合的内容,这提高了效率,如果对应的xml不存在则重新创建一个对应的xml文件。
@Override
public SharedPreferences getSharedPreferences(String name,int mode){
SharedPreferences sp;
//...
sp=packagePrefs.get(name);
if(sp==null){
File prefsFile=getSharedPrefsFile(name);
//该构造方法会调用startLoadFromDisk();把数据从硬盘加载到内存
sp =new SharedPreferencesImpl(prefsFile,mode);
packagePrefs.put(name,sp);
//...
return sp;
}
}
- put写操作:写操作也有两步,一是把数据先写入内存中,即map集合,二是把数据写入硬盘文件中。这样才能保证数据的完整性,写操作有两个提交的方式:
commit():线程安全,性能慢,一般来说在当前线程完成写文件操作。
apply(): 线程不安全,性能高,异步处理IO操作,一定会把这个写文件操作放入一个 SingleThreadExecutor 线程池中处理 - SharedPreferences 在第一次创建后会一直维持一个Singleton, 每次调用getSharedPreferences()都返回唯一的一个实例
SharedPreferences a=getSharedPreferences("test",0);
SharedPreferences b=getSharedPreferences("test",0);
SharedPreferences c=getSharedPreferences("test",0);
Log.i(TAG,"result:"+(a==b)+","+(b==c));
//9-10 09:15:17.810 2287-2287/com.xing.mayapplication l/MainActivity: result:true,true
SharedPreferences 使用封装:
由于SharedPreferences的key 与 value 其实最终都是以String类型存在,所以可以这样写一个SharedPreferences工具类:
/**
* SharedPreferences工具
*/
public class PerferenceManager{
private static final String PERF_NAME="com.xing_util.perf";
private static final int CURRENT_VERSION_CODE=1;
private volatile static PerferenceManager instance;
private final SharedPreferences preferences;
private PreferenceManager(Context context){
preferences=context.getSharedPreferences(PERF_NAME,Context.MODE_PRIVATE);
checkPrefVersion();
}
public static PerferenceManager getInstance(Context context){
if(instance==null){
synchronized(PerferenceManager.class){
if(instance==null)
instance=new PerferenceManager(context);
}
}
return instance;
}
public final void putValue(String key,String value){
preferences.edit().putString(key,value).apply();
}
public final String getValue(String key){
checkIsLegal(key);
return preferences.getString(key,"");
}
public final void deleteValue(String key){
checkIsLegal(key);
preferences.edit().remove(key).apply();
}
public final void clear(){
preferences.edit().clear().apply();
}
private void checkIsLegal(String key){
if(TextUtils.isEmpty(key))
throw new IllegalArgumentException("this parameter is illegal,key:"+key);
}
private void checkPrefVersion(){
final int oldVersion=preferences.getInt(PERF_NAME,0);
if (oldVersion<CURRENT_VERSION_CODE){
preferences.edit()
.clear()
.putInt(PERF_NAME,CURRENT_VERSION_CODE).apply();
}
}
}
由于应用版本升级时并不会删除SharedPreferences文件,所以可以加个版本判断,来进行一些数据更新,从上面看来,由于每次调用getSharedPreferences()都会有IO操作,当内容比较多时,那么就不适宜在Application 的onCreate 中进行SharedPreferences 文件初始化了,最好的办法是开个子线程去完成它的创建和数据的预加载!!!