一矾柜,獲取SharedPreferences對象
從Activity獲取SharedPreferences對象的代碼追蹤就谜,可以發(fā)現(xiàn)其是在ContextWrapper中通過context對象方法獲取的丧荐。
mBase.getSharedPreferences(name, mode)
那context中是如何創(chuàng)建對象的呢:
1.context對象
Activity中context對象的創(chuàng)建,肯定是要從Activity的創(chuàng)建找起虹统。
ActivityThread中:handleMessage->handleLaunchActivity->performLaunchActivity->createBaseContextForActivity
ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
在createBaseContextForActivity中可以看到ContextImpl是創(chuàng)建context的主要類车荔。
2.ContextImpl
return new ContextImpl(null, mainThread,
packageInfo, activityToken, null, false, null, null);
通過createActivityContext方法忧便,可以看到appContext對象時(shí)new ContextImpl本身創(chuàng)建的。
由此可以知道,contex是ContextImpl對象實(shí)現(xiàn)的砍艾。
3.創(chuàng)建SharedPreferences對象
既然知道context對象的實(shí)現(xiàn)類脆荷,就可以找出SharedPreferences如何創(chuàng)建了蜓谋。
在getSharedPreferences方法中
File prefsFile = getSharedPrefsFile(name);
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;
這段代碼可以知道,先獲得存儲數(shù)據(jù)的文件孤澎,然后創(chuàng)建SharedPreferencesImpl實(shí)例欠窒,SharedPreferencesImpl就是實(shí)現(xiàn)SharedPreferences的實(shí)現(xiàn)類岖妄。
3.1 獲取存儲數(shù)據(jù)的文件
getSharedPrefsFile中:
return makeFilename(getPreferencesDir(), name + ".xml");
getPreferencesDir中:
mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
getDataDirFile中
return mPackageInfo.getDataDirFile();
可以看出荐虐,存儲數(shù)據(jù)的文件是在app所在數(shù)據(jù)目錄中創(chuàng)建的一個(gè)shared_prefs目錄下的文件丸凭。簡單來說如下:
new File("/data/data/"+context.getPackageName()+"/shared_prefs/"+shareName+".xml")
3.2 獲取SharedPreferencesImpl對象
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = false;
mMap = null;
startLoadFromDisk();
}
makeBackupFile創(chuàng)建了一個(gè)備份文件惜犀,在startLoadFromDisk則使用線程獲取存儲文件中的值存儲在mMap中虽界,利用備份文件和mLoaded配合使用在多線程下使用SharedPreferences獲取存儲數(shù)據(jù)更加安全。
4.獲取對象中的參數(shù)mode
- Context.MODE_PRIVATE:為默認(rèn)操作模式,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問,在該模式下,寫入的內(nèi)容會覆蓋原文件的內(nèi)容
- Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件.
- Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應(yīng)用是否有權(quán)限讀寫該文件.
- MODE_WORLD_READABLE:表示當(dāng)前文件可以被其他應(yīng)用讀取.
- MODE_WORLD_WRITEABLE:表示當(dāng)前文件可以被其他應(yīng)用寫入.
mode主要在writeToFile中存儲數(shù)據(jù)后使用撇吞,而writeToFile在enqueueDiskWrite中使用牍颈,enqueueDiskWrite主要在apply方法中和commit方法中起作用琅关,而這兩個(gè)方法是修改數(shù)據(jù)后提交的方法。所以mode的功能是在寫入數(shù)據(jù)后人乓,更改存儲文件的權(quán)限作用。
二碰缔,使用
1 寫入
以下是簡單寫入操作金抡。
Editor editor = sharedPreferences.edit();
editor.putString(key, value);
editor.commit();
editor.clear();
其中Editor是操作數(shù)據(jù)寫入的主要對象腌且,EditorImpl是其實(shí)現(xiàn)類。
put操作是將鍵值對存入Editor的mModified對象中巫击,mModified是個(gè)map對象精续。
commit(apply)操作是將mModified對象內(nèi)存中的數(shù)據(jù),寫入磁盤文件中顷级。
先使用MemoryCommitResult對象存儲mModified中的數(shù)據(jù)确垫,MemoryCommitResult對象主要是方便對數(shù)據(jù)寫入磁盤操作,里面含有操作狀態(tài)翔冀。
下面這個(gè)方法是實(shí)現(xiàn)數(shù)據(jù)寫入磁盤的方法
SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
而這個(gè)方法中橘蜜,writeToFile方法是實(shí)現(xiàn)數(shù)據(jù)的寫入计福。簡略為:
......
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
+ " to backup file " + mBackupFile);
mcr.setDiskWriteResult(false);
return;
}
} else {
mFile.delete();
}
//寫入數(shù)據(jù)操作省略
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
......
可以看出徽职,mBackupFile又起到了多線程使用安全的作用,而設(shè)置的model说订,在寫入完成后,設(shè)置了文件的權(quán)限钙姊。
2.讀取數(shù)據(jù)
一下是簡單的獲取數(shù)據(jù)操作
SharedPreferencessharedPreferences= getSharedPreferences(name,
model);
String value =sharedPreferences.getString(key, defValue);
與寫入不同煞额,它不需要Editor,直接獲取數(shù)據(jù)mMap對象中的數(shù)據(jù)沾谜。
3.不同應(yīng)用間讀取數(shù)據(jù)
我們已經(jīng)知道m(xù)ode的作用,也知道存儲文件是通過context對象從對應(yīng)的應(yīng)用文件中創(chuàng)建的婚温。所以要讀取其他應(yīng)用的文件栅螟,需要兩個(gè)條件:
- 要讀取應(yīng)用的context對象逆日,從而獲取SharedPreferences對象
- 對應(yīng)SharedPreferences文件的model要設(shè)置為可被其他應(yīng)用讀(寫)室抽。
Context otherAppsContext = createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences(name, Context.MODE_WORLD_READABLE);
String value = sharedPreferences.getString(key, defvalue);
總結(jié)
SharedPreferences是將數(shù)據(jù)存儲在對應(yīng)應(yīng)用目錄下shared_prefs文件夾下的xml文件中坪圾,通過context獲取SharedPreferences對象惑朦,通過Editor操作數(shù)據(jù)的寫入,mode設(shè)置SharedPreferences的模式病梢。