2012-11-19 102 views
0

我不喜歡Android的SharedPreferences類的工作方式。 我的主要原因是每次在應用程序的任何部分查找鍵值對時,都必須指定默認值。鑑於大多數應用程序可能會在多個地方調用這些值,這種做法真的有種促進預期應用/偏好的行爲錯誤,因爲沒有中心點來獲取你的默認設置。示例:Activity getBoolean(key133,false),Actvity B getBoolean(key133,true):問題。優先級覆蓋默認行爲

我通過指定/存儲在HashMap我需要的應用程序的優先級值規避這個問題,我有一個自定義SharedPreferences派生類,它懶洋洋地查找指定HashMap S中的默認值。我只是打電話說MyClass.getBoolean(鍵)或MyClass.getString(鍵),它在HashMap查找默認值,返回和存儲(.commit() - 荷蘭國際集團),如果不存在,就。默認行爲是撥打getBoolean(key, default_value)。這對性能也是有益的,因爲在應用程序初始化時存儲所有首選項是非常糟糕的性能。

解決了一個問題,但現在我有一個新的問題:所有Preference派生類都找不到默認值,因爲我無法使用我自己的SharedPreference派生方式來查詢默認應用程序設置。這導致我的應用程序工作正常,但我的設置實際上不是顯示默認值,因爲它們不是存儲(總是),但在第一次打開設置頁...

長話短說:我怎麼重寫Preference類阻止這個?

編輯:一些代碼來解釋這個問題,爲什麼我選擇了這條路

private final static Context context     = ApplicationSubclass.getApplicationContext_(); 
private final static SharedPreferences prefs   = PreferenceManager.getDefaultSharedPreferences(context); 
private final static SharedPreferences.Editor editor = prefs.edit(); 
public static Map<String, Boolean> booleans    = new HashMap<String, Boolean>(); 
public static Map<String, Integer> longs    = new HashMap<String, Integer>(); 
public static Map<String, String> strings    = new HashMap<String, String>(); 
public static Map<String, Integer> integers    = new HashMap<String, Integer>(); 

public aPreferences(){ 
    initialise(); 
}//end constructor 

public void initialise(){ 
    // setup default preferences 
    setBooleans(); 
    //setLongs(); 
    setStrings(); 
    //setIntegers(); 
}//end method 

private void setBooleans(){ 
    booleans.put("does_this_work", true); 
    booleans.put("is_it_easy", true); 
    booleans.put("is_it_free_of_problems", false); 
    // and some hundreds more 
}//end method 

private void setStrings(){ 
    strings.put("show_me", "Show me!"); 
    // and some hundreds more 
}//end method 

// work the magic here 
public boolean getBoolean(String key){ 
    if (!prefs.contains(key)) putBoolean(key, booleans.get(key)); 
    return prefs.getBoolean(key, booleans.get(key)); 
}//end method 

public void putBoolean(String key, boolean value){ 
    editor.putBoolean(key, value).commit(); 
}//end method 

這工作:

private static aPreferences values = new aPreferences(); 
if (values.getBoolean("does_this_work")) // value initialised upon first access 
    Log.d(getClass().getSimpleName(), values.getString("show_me")); 

這不:

CheckBoxPreference sound = new CheckBoxPreference(this); 
sound.setKey("does_this_work"); // value not initialised, so checkbox not checked 
sound.setTitle(getResources().getString(R.string.sound_title)); 
sound.setSummary(getResources().getString(R.string.sound_text)); 
root.addPreference(sound); 
+1

AFAIK,你沒有。首先,你必須重寫每個'Preference'子類。其次,我並沒有成功地讓首選項屏幕系統使用除Shared Shared的庫存實現以外的任何其他功能(例如,我自己的加密的SharedPreferences實現)。順便說一句,如果僅僅爲默認值使用靜態數據成員,或者調用'setDefaultValues()'來使用在首選項XML文件中定義的默認值,那麼是不是更簡單? – CommonsWare

+0

這裏有一些好點。我可以使用靜態數據成員,但是我正在使用'HashMap's,因爲我確實使用了'setDefaultValues()'方法,它會迭代地圖並寫入值。但是我注意到,寫入首選項需要5秒的時間。所以現在我只是在第一次訪問時啓動了這些值,其中'Preference'類不理解...... – slinden77

+0

加上,我有幾百個優先值...使用靜態數據成員只是有點麻煩 – slinden77

回答

0

我真的建議創建自己的偏好管理類來處理這樣的事情。如果您需要知道默認值是什麼,您可以設置您自己的全局get/set方法,並將默認值作爲公共靜態字段公開。類似這樣的:

public class MyPreferences { 

    private static final String INT_VALUE_1_KEY = "VALUE_1"; 
    public static final int INT_VALUE_1_DEFAULT = -1; 

    public static void setDefaults(Context c) { 
     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); 
     Editor edit = prefs.edit(); 

     if (!prefs.contains(INT_VALUE_1_KEY)) { 
      edit.putInt(INT_VALUE_1_KEY, INT_VALUE_1_DEFAULT); 
     } 
     // etc.. 

     edit.commit(); 
    } 

    public static int getValue1(Context c) { 
     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); 
     return prefs.getInt(INT_VALUE_1_KEY, INT_VALUE_1_DEFAULT); 
    } 
} 
+0

謝謝,但那是我所做的,我的問題是任何基於'Preference'的類都不知道如何處理這種存儲應用程序首選項的方式。 使用這些類很好,因爲您不需要指定默認值,它們只會查看「SharedPreferences」的值。但價值必須在那裏,否則它會導致設置屏幕看起來不對...... – slinden77

+1

啊,很正確 - 如果您使用PreferenceScreen/CheckBoxPreference/EditTextPreference等,我想您將不得不首先初始化。如果您在應用程序中啓動了一個AsyncTask,會在第一次運行時在後臺線程中調用MyPreferences.setDefaults(Context)? – Hexar