Onsharedpreferencechanged Not Fired If Change Occurs in Separate Activity

onSharedPreferenceChanged not fired if change occurs in separate activity?

The OnSharedPreferenceChangeListener gets garbage collected in your case if you use an anonymous class.

To solve that problem use the following code in PreferenceActivity to register and unregister a change listener:

public class MyActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener {

@Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}

@Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key)
{
// do stuff
}

Furthermore be aware that the listener only gets called if the actual value changes. Setting the same value again will not fire the listener.

see also SharedPreferences.onSharedPreferenceChangeListener not being called consistently

Can't get onSharedPreferenceChanged() to work

onSharedPreferenceChanged not fired if change occurs in separate activity?

public class MyActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener {

@Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}

@Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}

SharedPreferences.onSharedPreferenceChangeListener not being called consistently

This is a sneaky one. SharedPreferences keeps listeners in a WeakHashMap. This means that you cannot use an anonymous inner class as a listener, as it will become the target of garbage collection as soon as you leave the current scope. It will work at first, but eventually, will get garbage collected, removed from the WeakHashMap and stop working.

Keep a reference to the listener in a field of your class and you will be OK, provided your class instance is not destroyed.

i.e. instead of:

prefs.registerOnSharedPreferenceChangeListener(
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// Implementation
}
});

do this:

// Use instance field for listener
// It will not be gc'd as long as this instance is kept referenced
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// Implementation
}
};

prefs.registerOnSharedPreferenceChangeListener(listener);

The reason unregistering in the onDestroy method fixes the problem is because to do that you had to save the listener in a field, therefore preventing the issue. It's the saving the listener in a field that fixes the problem, not the unregistering in onDestroy.

UPDATE: The Android docs have been updated with warnings about this behavior. So, oddball behavior remains. But now it's documented.

onSharedPreferenceChanged doesn't proc, Kotlin/Android

I see two mistakes. The first is that you never register your listener. You have called unregisterOnSharedPreferenceChangeListener() in your onStart() instead of registerOnSharedPreferenceChangeListener().

Secondly, you are not listening to the same SharedPreferences as the settings Fragment is using. PreferenceFragmentCompat by default uses the default shared preferences of the whole application. But you are listening to preferences retrieved with Activity.getPreferences(), which are not the default preferences, but rather a SharedPreferences instance that is named after the Activity.

So you should switch to using default shared preferences, because the private shared preferences of the Activity will not be as easy to get a reference to in other activities.

I would also register in onCreate() instead of onStart() so you aren't registering multiple times. I don't know if that really matters, but the documentation doesn't specify what happens when you repeatedly register the same listener. Maybe it would fire the callback repeatedly, which could end up wasting your time hunting the bug later.

override fun onCreate() {
// ...
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this)
}

override fun onDestroy() {
super.onDestroy()
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this)
}

It is possible to specify the SharedPreferences that will be used by PreferenceFragmentCompat, but the default preferences are the easiest to use for settings that you want to access from across your application.

registerOnSharedPreferenceChangeListener not working for changes made in different process

Most likely, it is being garbage collected by gc. I have faced this problem before. Make a global variable which keeps a hard reference to the listener.

  OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// Implementation
}
};

The answer at SharedPreferences.onSharedPreferenceChangeListener not being called consistently explains it best

OnSharedPreferenceChangeListener fires when the user enters in the preference activity the first time

Just use a flag in sharedpreferences, just like that

 if( prefs.getBoolean( "preferenceFirstTime", true ) ) {
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("preferenceFirstTime", false);
editor.commit();
} else {
//this is not the first time
}

How to use OnSharedPreferenceChangeListener in Kotlin?

It looks like you're forgetting to register/unregister the listener:

https://stackoverflow.com/a/3799894/7434090

onSharedPreferenceChanged method - Called for all activities or just current activity?

It should hit areas 1 and 2 both. Shared Preferences are on a per-app basis IIRC.

See the documentation for more info.



Related Topics



Leave a reply



Submit