Sharedpreferences 內(nèi)部工作原理:
- 調(diào)用getSharedPreferences(); 創(chuàng)建一個(gè)SharedPreferences對(duì)象,其中會(huì)先判斷是否存在對(duì)應(yīng)xml文件败明,如果發(fā)現(xiàn)存在則會(huì)有一個(gè)預(yù)加載操作钟鸵,這個(gè)操作是把xml文件的內(nèi)容通過(guò)I/O操作和XmlUitl 解析后存入一個(gè)map對(duì)象仲吏,所以我們調(diào)用SharedPreferences::getString();等get操作實(shí)際上是不會(huì)對(duì)文件做I/O操作,而是直接訪問(wèn)剛剛的map集合的內(nèi)容肘习,這提高了效率近零,如果對(duì)應(yīng)的xml不存在則重新創(chuàng)建一個(gè)對(duì)應(yīng)的xml文件珠洗。
@Override
public SharedPreferences getSharedPreferences(String name,int mode){
SharedPreferences sp;
//...
sp=packagePrefs.get(name);
if(sp==null){
File prefsFile=getSharedPrefsFile(name);
//該構(gòu)造方法會(huì)調(diào)用startLoadFromDisk();把數(shù)據(jù)從硬盤加載到內(nèi)存
sp =new SharedPreferencesImpl(prefsFile,mode);
packagePrefs.put(name,sp);
//...
return sp;
}
}
- put寫操作:寫操作也有兩步溜歪,一是把數(shù)據(jù)先寫入內(nèi)存中,即map集合许蓖,二是把數(shù)據(jù)寫入硬盤文件中痹愚。這樣才能保證數(shù)據(jù)的完整性,寫操作有兩個(gè)提交的方式:
commit():線程安全蛔糯,性能慢拯腮,一般來(lái)說(shuō)在當(dāng)前線程完成寫文件操作。
apply(): 線程不安全蚁飒,性能高动壤,異步處理IO操作,一定會(huì)把這個(gè)寫文件操作放入一個(gè) SingleThreadExecutor 線程池中處理 - SharedPreferences 在第一次創(chuàng)建后會(huì)一直維持一個(gè)Singleton淮逻, 每次調(diào)用getSharedPreferences()都返回唯一的一個(gè)實(shí)例
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 其實(shí)最終都是以String類型存在琼懊,所以可以這樣寫一個(gè)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();
}
}
}
由于應(yīng)用版本升級(jí)時(shí)并不會(huì)刪除SharedPreferences文件阁簸,所以可以加個(gè)版本判斷,來(lái)進(jìn)行一些數(shù)據(jù)更新哼丈,從上面看來(lái)启妹,由于每次調(diào)用getSharedPreferences()都會(huì)有IO操作,當(dāng)內(nèi)容比較多時(shí)醉旦,那么就不適宜在Application 的onCreate 中進(jìn)行SharedPreferences 文件初始化了饶米,最好的辦法是開個(gè)子線程去完成它的創(chuàng)建和數(shù)據(jù)的預(yù)加載!3岛檬输!