### Ⅰ. 簡介
很多時候我們開發的軟件需要向用戶提供軟件參數設置功能,例如我們常用的 QQ,用戶可以設置是否允許陌生人添加自己為好友。對于軟件配置參數的保存,如果是window軟件通常我們會采用ini文件進行保存,如果是j2se應用,我們會采用properties屬性文件或者xml進行保存。如果是Android應用,我們最適合采用什么方式保存軟件配置參數呢?Android 平臺給我們提供了一個SharedPreferences類,它是一個輕量級的存儲類,特別適合用于保存軟件配置參數。SharedPreferences 類似過去Windows系統上的ini配置文件,但是它分為多種權限,可以全局共享訪問,最終是以xml方式來保存,整體效率來看不是特別的高,對于常規的輕量級而言比SQLite要好不少,如果真的存儲量不大可以考慮自己定義文件格式。xml 處理時Dalvik會通過自帶底層的本地XML Parser解析,比如XMLpull方式,這樣對于內存資源占用比較好。
使用 SharedPreferences保存數據,其背后是用xml文件存放數據,文件存放在/data/data/<package name>/shared_prefs目錄下(需要用戶的root權限)
SharedPreferences的使用非常簡單,能夠輕松的存放數據和讀取數據。SharedPreferences只能保存簡單類型的數據,例如,String、int等。一般會將復雜類型的數據轉換成Base64編碼,然后將轉換后的數據以字符串的形式保存在 XML文件中,再用SharedPreferences保存。這種方式應該是用起來最簡單的Android讀寫外部數據的方法了。他的用法基本上和 J2SE(java.util.prefs.Preferences)中的用法一樣,以一種簡單、透明的方式來保存一些用戶個性化設置的字體、顏色、位置等參數信息。一般的應用程序都會提供“設置”或者“首選項”的這樣的界面,那么這些設置最后就可以 通過Preferences來保存,而程序員不需要知道它到底以什么形式保存的,保存在了什么地方。當然,如果你愿意保存其他的東西,也沒有什么限制。只 是在性能上不知道會有什么問題。
### Ⅱ. 使用
使用SharedPreferences保存key-value對的步驟如下:
(1)使用Activity類的getSharedPreferences方法獲得SharedPreferences對象,其中存儲key-value的文件的名稱由getSharedPreferences方法的第一個參數指定。
(2)使用SharedPreferences接口的edit獲得SharedPreferences.Editor對象。
(3)通過SharedPreferences.Editor接口的putXxx方法保存key-value對。其中Xxx表示不同的數據類型。例如:字符串類型的value需要用putString方法。
(4)通過SharedPreferences.Editor接口的commit方法保存key-value對。commit方法相當于數據庫事務中的提交(commit)操作。
具體代碼的書寫流程為:
#### A、存放數據信息
~~~
//1、打開Preferences,名稱為setting,如果存在則打開它,否則創建新的Preferences
SharedPreferences settings = getSharedPreferences(“setting”, 0);
//2、讓setting處于編輯狀態
SharedPreferences.Editor editor = settings.edit();
//3、存放數據
editor.putString(“name”,”ATAAW”);
editor.putString(“URL”,”ATAAW.COM”);
//4、完成提交
editor.commit();
~~~
因為SharedPreferences背后是使用xml文件保存數據,getSharedPreferences(name,mode)方法的第一個參數用于指定該文件的名稱,名稱不用帶后綴,后綴會由Android自動加上。方法的第二個參數指定文件的操作模式,共有四種操作模式。

- Activity.MODE_PRIVATE,//默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容,如果想把新寫入的內容追加到原文件中,可以使用Activity.MODE_APPEND?
- Activity.MODE_WORLD_READABLE,//表示當前文件可以被其他應用讀取,?
- Activity.MODE_WORLD_WRITEABLE,//表示當前文件可以被其他應用寫入;?
??????????????????????????????????? //如果希望文件被其他應用讀和寫,可以傳入:Activity.MODE_WORLD_READABLE+Activity.MODE_WORLD_WRITEABLE
- Activity.MODE_APPEND//該模式會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件?
如果希望SharedPreferences背后使用的xml文件能被其他應用讀和寫,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。
另外Activity還提供了另一個getPreferences(mode)方法操作SharedPreferences,這個方法默認使用當前類不帶包名的類名作為文件的名稱。
#### B、讀取數據信息
~~~
//1、獲取Preferences
SharedPreferences settings = getSharedPreferences(“setting”, 0);
//2、取出數據
String name = settings.getString(“name”,”默認值”);//getString()第二個參數為缺省值,如果preference中不存在該key,將返回缺省值
String url = setting.getString(“URL”,”default”);
~~~
//以上就是Android中SharedPreferences的使用方法,其中創建的Preferences文件存放位置可以在Eclipse中查看:
DDMS->File Explorer /<package name>/shared_prefs/setting.xml
### 運行機制
####
#### Context內部實現
getSharedPreferences()方法本身是Context這個接口中定義的一個抽象方法,由ContextImpl類負責實現。
1 、調用getSharedPreferences()獲取對應的的文件,該函數實現功能如下:
~~~
//Context類靜態數據集合,以鍵值對保存了所有讀取該xml文件后所形成的數據集合
private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
new HashMap<File, SharedPreferencesImpl>();
@Override
public SharedPreferences getSharedPreferences(String name, int mode){
//其所對應的SharedPreferencesImpl對象 ,該對象已一個HashMap集合保存了我們對該文件序列化結果
SharedPreferencesImpl sp;
File f = getSharedPrefsFile(name); //該包下是否存在對應的文件,不存在就新建一個
synchronized (sSharedPrefs) { //是否已經讀取過該文件,是就直接返回該SharedPreferences對象
sp = sSharedPrefs.get(f);
if (sp != null && !sp.hasFileChanged()) {
//Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
return sp;
}
}
//以下為序列化該xml文件,同時將數據寫到map集合中
Map map = null;
if (f.exists() && f.canRead()) {
try {
str = new FileInputStream(f);
map = XmlUtils.readMapXml(str);
str.close();
}
...
}
synchronized (sSharedPrefs) {
if (sp != null) {
//Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
sp.replace(map); //更新數據集合
} else {
sp = sSharedPrefs.get(f);
if (sp == null) {
//新建一個SharedPreferencesImpl對象,并且設置其相關屬性
sp = new SharedPreferencesImpl(f, mode, map);
sSharedPrefs.put(f, sp);
}
}
return sp;
}
}
~~~
2、 SharedPreferences 不過是個接口,它定義了一些操作xml文件的方法,其真正實現類為SharedPreferencesImpl ,該類是ContextIml的內部類,該類如下:
~~~
//這種形式我們在分析Context ContextIml時接觸過
//SharedPreferences只是一種接口,其真正實現類是SharedPreferencesImpl類
private static final class SharedPreferencesImpl implements SharedPreferences{
private Map mMap; //保存了該文件序列化結果后的操作, 鍵值對形式
//通過key值獲取對應的value值
public String getString(String key, String defValue) {
synchronized (this) {
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
...
//獲得該SharedPreferencesImpl對象對應的Edito類,對數據進行操作
public final class EditorImpl implements Editor {
private final Map<String, Object> mModified = Maps.newHashMap(); //保存了對鍵值變化的集合
}
}
~~~
參考:
http://blog.csdn.net/wxyyxc1992/article/details/17222841
- 前言
- Appcompat_V7問題
- This Android SDK requires Android Developer Toolkit version 23.0.0 or above
- 創建Android項目不自動生成Activity,layout目錄為空
- 新建android項目gen目錄下未生成R文件
- 手機安全衛士02:splash界面ui
- 知識點:Android控件系列之Toast
- 手機安全衛士03:獲取更新的服務器配置,顯示更新對話框
- 異常處理:android.os.NetworkOnMainThreadException--多線程問題
- 知識點:Android控件系列之對話框AlertDialog.Builder
- 手機安全衛士04_01:界面(Activity)之間的切換,Activity和任務棧
- 知識點:Android控件系列之ProgressDialog與ProgressBar
- 手機安全衛士04_02:從服務器下載并安裝新版本安裝包
- 知識點:Intent
- 知識點:Adapter適配器
- 手機安全衛士05_1:程序主界面
- 手機安全衛士05_2:程序主界面,為每個條目添加事件
- 知識點:動態設置布局LayoutInflater
- 知識點:SharedPreferences
- 手機安全衛士06-手機防盜之自定義對話框
- 手機安全衛士07-手機防盜之進入限制
- 手機安全衛士08-一些布局和顯示的細節:State List
- 手機安全衛士09-手機防盜界面設置向導1
- 手機安全衛士10-設置向導之綁定SIM卡