4
  1. 我通过读取文本文件并对其进行解析来加载一组新设置。
  2. 对于我在那里找到的每个设置,我提取值并更新相应的首选项(无论是 CheckPreference、ListPreference 还是 EditTextPreference)。
  3. 所有这些都是从设置片段完成的。这意味着在我进行更改时,首选项屏幕会显示在视图中。
  4. 因为我以编程方式更改值 ( editor().commit),所以不会触发 onSharedPreferenceChange()。

这就是为什么我之后使用此代码刷新所有首选项的原因:

private void refreshPreferences() {
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    for(int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
        onSharedPreferenceChanged(sp, getPreferenceScreen().getPreference(i).getKey());
    }
}

它完美地工作。我只是想知道是否存在使所有首选项无效的系统调用会达到相同的结果(对 onSharedPreferenceChanged() 的自动调用)

我不是肛门,我只是不喜欢手动调用应该由操作系统调用的方法。

编辑
这是我当前更改首选项的代码。我之前尝试使用编辑器进行更改,但也没有生成 onSharePreferncesChanged() 调用。
来源:它是从文件中读取的多行字符串

private enum Type { INT, BOOLEAN, EDITTEXT, LIST }; 

private void loadPreference(int key, char [] source, Type t) {
    String s = new String(source);
    Log.i(TAG, "+ loadPreference(key:" + key + ", source:(" + s + "), t:" + t + ")");
    String sKey = getText(key).toString();
    Matcher m;
    Preference p = findPreference(sKey);
    switch( t ) {
    case BOOLEAN:
        m = Pattern.compile("(?m)^" + sKey + "=\"(true|false)\"$").matcher(s);
        if( m.find() ) ((CheckBoxPreference)p).setChecked(m.group(1).equals("true"));
        break;
    case INT:
        m = Pattern.compile("(?m)^" + sKey + "=\"(\\d+)\"$").matcher(s);
        if( m.find() ) ((EditTextPreference)p).setText(m.group(1));
        break;
    case EDITTEXT:
        m = Pattern.compile("(?m)^" + sKey + "=\"(.*)\"$").matcher(s);
        if( m.find() ) ((EditTextPreference)p).setText(m.group(1));
        break;
    case LIST:
        m = Pattern.compile("(?m)^" + sKey + "=\"(\\d+)\"$").matcher(s);
        if( m.find() ) ((ListPreference)p).setValueIndex(Integer.valueOf(m.group(1)));
        break;
    default:
    }
    Log.i(TAG, "- loadPreference()");
}

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    Log.i(TAG, "+ onSharedPreferenceChanged(prefs:" + prefs + ", key:" + key + ")");
    if( key != null ) {
        updatePreference(prefs, key);
        updateSummary(findPreference(key));
    } else {
        Log.e(TAG, "Preference without key!");
    }
    Log.i(TAG, "- onSharedPreferenceChanged()");
}

@Override
public void onResume() {
    Log.i(TAG, "+ onResume()");
    super.onResume();
    // Set up a listener
    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    Log.i(TAG, "- onResume()");
}

@Override
public void onPause() {
    Log.i(TAG, "+ onPause()");
    super.onPause();
    // Unregister the listener
    getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    Log.i(TAG, "- onPause()");
}
4

2 回答 2

4

实现此目的的符合准则的方法是使用OnSharedPreferenceChangeListener.

在你问题的第 4 点,你说

因为我以编程方式更改值,所以不会触发 onSharedPreferenceChange()。

这取决于您如何更改设置。在你的第 2 点,你说

对于我在那里找到的每个设置,我都会提取值并更新相应的首选项...

请确保您使用设置编辑器并提交您的更改,类似于以下内容:

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = sp.edit();
editor.putString("key","value"); // your updated setting
editor.commit();

如果您的其他类正确实现了 anOnSharedPreferenceChangeListener并通过调用registerOnSharedPreferenceChangeListener(this)您的 default注册了它SharedPreferences,您应该能够在onSharedPreferenceChanged()方法中侦听这些更改。

至少这是Dev Guide on Settings中的文章所建议的,并且我已经以类似的方式成功实现了它(“以编程方式”更改设置)。

更新的答案:
由于您的评论说上述内容不起作用,我再次查看了我的代码。确实,我认为您想从不同的班级实现这一目标,所以我弄错了您的问题。

如果您在PreferenceFragment(或PreferenceActivity)中,您也可以实现该OnSharedPreferenceChangeListener接口,但将其注册为您当前显示的首选项PreferenceScreen。最佳做法是onResume()通过调用注册它

getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);

然后注销onPause()

getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);

如前所述,您会收到您的偏好onSharedPreferenceChanged()更改PreferenceFragment。这是(现在是真实的)它在我的代码中的工作方式。

于 2013-02-18T00:32:33.810 回答
1

当新值等于前一个值时,不会触发 OnSharedPreferencesChangeListener。在这种情况下 SharedPreferences 不会更新。

我在适当的时候解决了这个问题,清除了旧值。

于 2019-03-21T12:33:07.920 回答