2012-11-19 106 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