Paul Naveda
Paul Naveda

Reputation: 762

Change in shared preference not firing

I have a Floating Action Button in my layout. Users can choose the position of this button, left or right. This can be selected in the preferences.

The code to do this works OK, but a change in the preference is not detected by the listener.

If the app is restarted, the Floating Action Button is displayed according to the new preference, so I know the process with this preference works, but unfortunately the listener seems to fail.

What do I have to do to get the listener firing when the preference has changed?

Listener in my MainActivity:

private final SharedPreferences.OnSharedPreferenceChangeListener 
        mPositionFabListener = new SharedPreferences.OnSharedPreferenceChangeListener() {

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

        Log.e(TAG,"Are we getting here?");
        // We do not get here when preference has changed. Why not??

        // Code to update Floating Action Button to new position

    }
};

I register the listener in the onResume() method of the MainActivity and unregister in the onPause().

@Override
protected void onResume() {
    super.onResume();
    PrefUtils.registerOnPrefChangeListener(mPositionFabListener);
}

@Override
protected void onPause() {
    PrefUtils.unregisterOnPrefChangeListener(mPositionFabListener);
    super.onPause();
}

The registerOnPrefChangeListener method is declared in a seperate class:

public class PrefUtils {

public static boolean getBoolean(String key, boolean defValue) {
    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext());
    return settings.getBoolean(key, defValue);
}

public static void putBoolean(String key, boolean value) {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit();
    editor.putBoolean(key, value);
    editor.apply();
}

public static int getInt(String key, int defValue) {
    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext());
    return settings.getInt(key, defValue);
}

public static void putInt(String key, int value) {
    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit();
    editor.putInt(key, value);
    editor.apply();
}

public static void registerOnPrefChangeListener(OnSharedPreferenceChangeListener listener) {
    try {
        PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).registerOnSharedPreferenceChangeListener(listener);
    } catch (Exception ignored) {}
}

public static void unregisterOnPrefChangeListener(OnSharedPreferenceChangeListener listener) {
    try {
        PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).unregisterOnSharedPreferenceChangeListener(listener);
    } catch (Exception ignored) {}
}

}

UPDATE: In the GeneralPrefsFragment class I put in this listener for testing purposes. This listener is working. So why does it not work in the MainActivity?

public class GeneralPrefsFragment extends PreferenceFragment {


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

   Preference  preference = findPreference(PrefUtils.POSITION_FLOATING_MENU_BUTTON);
   Preference.OnPreferenceChangeListener mListener = new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            PrefUtils.putBoolean(PrefUtils.POSITION_FLOATING_MENU_BUTTON, Boolean.TRUE.equals(newValue));

            PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit().commit(); // to be sure all prefs are written

            Log.e(TAG, "The listener in " + TAG + " is listening");

            // This listener is fired as soon as changes in the preference are made!
            // Why is the same kind of listener not fired in the MainActivity?

            return true;
        }
    };
    preference.setOnPreferenceChangeListener(mListener);


}

}

SOLUTION: I got a fix. I still do not know why the former setup didn't work, but I got it working, thanks to the code in this answer.

In the MainAcivity's onCreate() method I placed the following listener and this one gets triggered when the preferences have changed.

SharedPreferences prefs =
        PreferenceManager.getDefaultSharedPreferences(this);

SharedPreferences.OnSharedPreferenceChangeListener mPrefsFabListener =
        new SharedPreferences.OnSharedPreferenceChangeListener() {
            public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
                if (PrefUtils.POSITION_FLOATING_MENU_BUTTON.equals(key)) {
                    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
                    CoordinatorLayout.LayoutParams paramsFab = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
                    if (PrefUtils.getBoolean(PrefUtils.POSITION_FLOATING_MENU_BUTTON, false)) {
                        paramsFab.gravity = Gravity.BOTTOM | Gravity.START;
                    } else {
                        paramsFab.gravity = Gravity.BOTTOM | Gravity.END;
                    }
                }
            }
        };
prefs.registerOnSharedPreferenceChangeListener(mPrefsFabListener); 

Upvotes: 2

Views: 1117

Answers (1)

Paul Naveda
Paul Naveda

Reputation: 762

The OnSharedPreferenceChangeListener gets unregistered in the onPause() method of the MainAcitivity. That is a problem, because the MainActivity gets paused as soon as the General Preferences Activity is started in order to change the preferences. So, the listener is unregistered and therefore not listening right at the point where it is needed!

I removed the unregisterOnPrefChangeListener from the onPause() and put in the following code. This worked perfectly!

@Override
protected void onDestroy() {
    PrefUtils.unregisterOnPrefChangeListener(mPositionFabListener);
    super.onDestroy();
}

Upvotes: 1

Related Questions