Reputation: 8350
editor().commit
), onSharedPreferenceChange() is not triggered. That's why I refresh all preferences afterwards with this code:
private void refreshPreferences() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
for(int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
onSharedPreferenceChanged(sp, getPreferenceScreen().getPreference(i).getKey());
}
}
It works perfectly. I just wonder if a system call to invalidate all preferences exists that would achieve the same result (an automatic call to onSharedPreferenceChanged() )
I am not anal, I am just not fond of manually calling methods that are supposed to be called by the OS.
Edit
This is my current code that changes a preference. I tried before to change with editor but was also not generating onSharePreferncesChanged() calls.
source: it's a multiline string that was read from a file
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()");
}
Upvotes: 5
Views: 5638
Reputation: 11
OnSharedPreferencesChangeListener is not triggered when the new value is equal to the previous value. In this case SharedPreferences is not updated.
I worked around this clearing the old value when appropriate.
Upvotes: 1
Reputation: 8230
The guideline-compliant way to achieve this is to use an OnSharedPreferenceChangeListener
.
In point 4 of your question, you say
Because I change the vaules programatically, onSharedPreferenceChange() is not triggered.
This depends on how you change the settings. In your point 2, you say
For each setting I found there I extract the value and update the corresponding preference...
Please make sure that you use the settings editor and commit your changes, similar to this:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = sp.edit();
editor.putString("key","value"); // your updated setting
editor.commit();
If your other class properly implements an OnSharedPreferenceChangeListener
and has registered it by calling registerOnSharedPreferenceChangeListener(this)
on your default SharedPreferences
, you should be able to listen for these changes in the onSharedPreferenceChanged()
method.
At least that's what the article in the Dev Guide on Settings suggests and I have implemented it successfully in a similar way ("programmatically" changing settings).
Updated answer:
Since your comment says the above doesn't work, I had a look in my code again. Indeed, I got your question wrong by thinking you want to achieve this from a different class.
If you are in a PreferenceFragment
(or PreferenceActivity
), you can also implement the OnSharedPreferenceChangeListener
interface, but register it for the preferences displayed in your current PreferenceScreen
. Best practice would be to register it in onResume()
by calling
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
and then unregister in onPause()
:
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
As described previously, you receive the preference changes in onSharedPreferenceChanged()
of your PreferenceFragment
then. This is (now for real) the way it works in my code.
Upvotes: 4