My favorites | Sign in
Project Home Wiki Issues Source
Search
for
AndroidPreference  
儲存資訊
tw, preference
Updated Aug 15, 2011 by gasolin

我們都知道,一般人身高的變化程度,比起體重的變化程度小的多。

因此就設計一款 BMI 計算程式來說,如果能在使用者第一次輸入身高體重值後,程式能幫我們預先記住上次輸入過的身高,那麼等到下次啟動程式時,便只需要輸入體重。這麼一來,減少了使用者重複輸入的麻煩,在使用上就更方便了。使用者應該會喜歡這個便利的功能吧。

使用偏好設定

打開「src/com/demo/android/bmi/Bmi.java」,在「onCreate」和「onPause」中加入「Preference」(偏好設定)相關的程式碼。完整的程式碼如下:

public class Bmi extends Activity {
	private static final String TAG = "Bmi";
        public static final String PREF = "BMI_PREF";
	public static final String PREF_HEIGHT = "BMI_Height";
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViews();
        restorePrefs();
        setListensers();
    }

    // Restore preferences
    private void restorePrefs()
    {
    	SharedPreferences settings = getSharedPreferences(PREF, 0);
    	String pref_height = settings.getString(PREF_HEIGHT, "");
    	if(! "".equals(pref_height))
    	{
    		field_height.setText(pref_height);
    		field_weight.requestFocus();
    	}
    }

......

	@Override
	protected void onPause(){
		super.onPause();
		// Save user preferences. use Editor object to make changes.
		SharedPreferences settings = getSharedPreferences(PREF, 0);
		settings.edit()
		  .putString(PREF_HEIGHT, field_height.getText().toString())
		  .commit();
	}

講解

取得偏好設定

    // Restore preferences
    private void restorePrefs()
    {
    	SharedPreferences settings = getSharedPreferences(PREF, 0);
    	String pref_height = settings.getString(PREF_HEIGHT, "");
    	if(! "".equals(pref_height))
    	{
    		field_height.setText(pref_height);
    		field_weight.requestFocus();
        }
    }

我們在「onCreate」函式中,加入一行 「restorePrefs」呼叫。並在「onCreate」函式外,再定義一個「restorePrefs」函式如上。

SharedPreferences settings = getSharedPreferences(PREF, 0);

我們宣告了一個偏好設定(SharedPreferences)型別「settings」,並使用「getSharedPreferences」函式,來尋找系統中有無符合以「BMI_PREF」字串(PREF 參數)作為檔名的偏好設定檔。如果有符合條件的偏好設定檔存在的話,就將這個偏好設定指定使用「settings」作為代號來操作。如果沒有的話,「getSharedPreferences」函式會回傳空值給「settings」。

    String pref_height = settings.getString(PREF_HEIGHT, "");

我們可以透過「getXXX」函式,來從偏好設定(SharedPreferences)讀取不同型別的內容。例如本例中使用「getString」來讀取文字類型的資訊。當「PREF_HEIGHT」偏好設定參數存在時,字串「pref_height」就會得到偏好設定參數的內容。如果不存在「PREF_HEIGHT」這個偏好設定參數時,字串「pref_height」則會得到一個空字串。

if(! "".equals(pref_height))
    	{
    		field_height.setText(pref_height);
            ...
        }

當「pref_height」字串存在時,我們將 field_height 欄位內容設定成偏好設定參數中取出的值。

field_weight.requestFocus();

同時,因為身高欄位已經預先填好了,使用者只需要再填入體重值即可開始計算自己的 BMI 值。但是當程式一執行,預設的焦點欄位(游標)還是停在「身高」欄位上。因此我們可以在「field_weight」欄位識別符號上,使用「requestFocus」函式,來手動將焦點欄位改到「體重」欄位上。這樣當使用者要輸入時,如果之前已經輸入過「身高」,那麼程式就會自動幫忙填好上次輸入的身高,並把焦點欄位設置到「體重」欄位上,使用者只需直接輸入體重數字就可以了。

如果只加入了「取得偏好設定」這段的程式碼,就運行模擬器來看看結果,會發現我們寫在「restorePrefs」函式中的程式碼,目前都還沒有發生作用。這是因為我們尚未在程式中儲存任何偏好設定。接著,我們將在程式中加入儲存偏好設定的程式碼,好能在開啟 Activity 時讀到偏好設定。

儲存偏好設定

    	@Override
	protected void onPause(){
		super.onPause();
		// Save user preferences. use Editor object to make changes.
		SharedPreferences settings = getSharedPreferences(PREF, 0);
		settings.edit()
		  .putString(PREF_HEIGHT, field_height.getText().toString())
		  .commit();
	}

當我們使用「Home」、「Back」按鈕或其他方式離開當前的 Activity 時,我們才把身高的值儲存到偏好設定中。根據上一章活動的生命週期,我們知道停止當前螢幕動作的狀態是「onPause」狀態。因此我們覆載(Override)了「onPause」函式,在其中加入儲存身高偏好設定的程式碼。「super.onPause」的作用是先將原本的「onPause」函式執行一遍。

SharedPreferences settings = getSharedPreferences(PREF, 0);

我們宣告了一個偏好設定(SharedPreferences)型別「settings」,並使用「getSharedPreferences」函式,來尋找系統中有無符合以「BMI_PREF」字串(PREF 參數)作為檔名的偏好設定檔。如果有符合條件的偏好設定檔存在的話,就將這個偏好設定指定使用「settings」作為代號來操作。如果沒有的話,「getSharedPreferences」函式會回傳 0 給「settings」。

    settings.edit()
		  .putString(PREF_HEIGHT, field_height.getText().toString())
		  .commit();

在此我們串接了三個 settings 擁有的函式:「edit」、「putString」,和「commit」。 要改變偏好設定(SharedPreferences)型別的內容,需要透過「edit」函式來編輯。編輯結束後,要透過「commit」函式來將改變寫到系統中。我們可以透過「putXXX」函式來為偏好設定(SharedPreferences)填入不同型別的內容。例如本例中使用「putString」來寫入文字類型的資訊(讀者也可以試試用 putInt 或 putFloat 函式來直接將身高值儲存成整數或浮點數)。

本例中「putString」函式所執行的動作,是透過「field_height」介面元件識別符號來取得身高的字串後,將字串儲存到「PREF_HEIGHT」所代表的偏好設定參數中。

參考資料

< 活動的生命週期 | 回目錄 | 發佈到 Android 市場(Market) >


對於本章,您還期望知道什麼樣的內容呢?請在下方提出建議!

Comment by zxhwo...@hotmail.com, Nov 13, 2008

希望讲解下她的的数据库,ContentProvider?类等等。 小建议下,这章节最好介绍下android的数据库,否则让我以为android的db如此的弱。呵呵

Comment by project member gasolin, Nov 16, 2008

飯要一口口吃,總有天會講到的 :)

Comment by mark...@gmail.com, Oct 21, 2009

gasolin您好,我買的書是二版二刷,裡面是用onStop來代替onPause,但onPause似乎印成了onPalse了。

Comment by project member gasolin, Oct 21, 2009

抱歉, onPalse 是 onPause 的筆誤 XD

Comment by jerrys...@gmail.com, Nov 25, 2009

SharedPreferences? settings = getSharedPreferences(PREF, 0); String pref_height = settings.getString(PREF_HEIGHT, "");

請問當傳回 0 時 ( settings = 0 ), settings.getString() 可以正常運作嗎 ?

Comment by project member gasolin, Nov 25, 2009

當然不行呀。SharedPreferences?是 developer 完全可以控制的,會傳回0(找不到)表示自己有其他地方寫錯了

Comment by luoyu...@gmail.com, Feb 6, 2010
SharedPreferences? settings = getSharedPreferences(PREF, 0);

后面参数0应该表示的是私有控制的模式,而不是要回传给settings吧 :)

Comment by project member gasolin, Feb 6, 2010

luoyuoki, 你是對的,我這樣寫會很容易被誤會 :p

Comment by zhibo...@gmail.com, Mar 5, 2010

Desired preferences file. If a preferences file by this name does not exist, it will be created when you retrieve an editor (SharedPreferences?.edit()) and then commit changes (Editor.commit()). 当文件不存在,只有edit和commit时才会被创建。 mode: 0(MODE_PRIVATE)指该文件仅能被当前 Activity 访问。

Comment by lp43si...@gmail.com, May 28, 2010

這一節「儲存資訊」的前一節是「活動的生命週期」,但是參考資料中卻是這樣子:< 傳送資料到新 Activity | 回目錄 | 發佈到 Android 市場(Market) >

Comment by project member gasolin, May 28, 2010

lp43simon, fixed, thanks :)

Comment by lp43si...@gmail.com, May 28, 2010

看到這一節的引言:「因此就設計一款 BMI 計算程式來說,如果能在使用者第一次輸入身高體重值後,程式能幫我們預先記住上次輸入過的身高,那麼等到下次啟動程式時,便只需要輸入體重。」,對葛大設計這個BMI程式教學的多角化感到感動和讚賞

Comment by jqgsnin...@hotmail.com, Sep 2, 2010

關於「getSharedPreferences」函式返回值的解釋似乎有誤。 If a preferences file by this name does not exist, it will be created when you retrieve an editor (SharedPreferences?.edit()) and then commit changes (Editor.commit()). 按照幫助文檔中所說,函式不會傳回空值。

Comment by k650...@gmail.com, Feb 20, 2011

gasolin 大大, 您好:

想請教一下, 您前面幾章有提過"「Bundle」可以保存程式上一次關閉(凍結)時的狀態。..."

不知道這個 SharedPreferences? 跟 Bundle 的差異是在哪兒呢?

還請撥冗解惑...3Q3Q~

Comment by project member gasolin, Feb 21, 2011

SharedPreferences?的資料會真的存到系統裡,Bundle在程式結束後就消失了

Comment by lam.chi....@gtempaccount.com, Aug 14, 2011

if(! "".equals(pref_height))

{
pref_height.setText(pref_height);
...
}
當「pref_height」字串存在時,我們將 field_height 欄位內容設定成偏好設定參數中取出的值。 pref_height.setText(pref_height);------->field_height.setText(pref_height);

Comment by project member gasolin, Aug 15, 2011
lam.chi....已修正,謝謝
Comment by mywa...@gmail.com, Oct 31, 2011

我有一個疑問,根據activity的生命周期,第一次執行Bmi這個activity 第一個執行的是onCreate(),而onCreate()會執行getSharedreferences ,因為是第一次執行且沒有用edit()照理說PREF的SharedPreferences?應該不存在, 等到onPause執行後,SharedPreference?因為edit()和commit()才被創建出來吧, 所以在onCreate執行getSharedreferences應該是找不到PREF的SharedPreferences?所以settings應該是0不是嗎? 這樣在onCreate()執行settings.getString() 應該會出問題吧

可是實際寫程式測試並沒有問題,讓我覺得很困惑 還有一個問題就是SharedPreference?的偏好設定檔可以存活多久啊

Comment by project member gasolin, Oct 31, 2011

SharedPreference?會存成一個內部的xml檔,因此沒存活期限制。第一次get時應該會自動建立

Comment by thisismy...@gmail.com, Dec 4, 2011

SharedPreferences? 會存成一個xml檔? 請問實體的路徑會在哪裡呢?bin資料夾底下嗎? 依此例來說,是會存成BMI_PREF.xml檔嗎?

Comment by project member gasolin, Dec 4, 2011

Google it, you'll get "/data/data/<package name>/shares_prefs/文件名.xml"

Comment by sonic238...@gmail.com, Jan 6, 2012

請問 在一開始定義了PREF_HEIGHT public static final String PREF_HEIGHT = "BMI_Height"; 在Restore preferences中有一句:String pref_height = settings.getString(PREF_HEIGHT, ""); 那PREF_HEIGHT不是一開始被定成"BMI_Height"了嗎? 為何第一次打開程式時身高欄不是預設為BMI_Height,而是空白?


Sign in to add a comment
Powered by Google Project Hosting