PreferenceFragment OnPreferenceClickListener() works only once

android, onclicklistener, reset, sharedpreferences

Solution

When you call the `setPreferenceScreen(null);` all the data and listeners of the screens is removed. Then by calling `addPreferencesFromResource(R.xml.preferences);` you add the data but not the listeners.

So to make `Preference` reset to work you need to add the listener again!

I suggest you create a method

private void addMyResetListener() {
    Preference reset = (Preference) findPreference("reset");

    reset.setOnPreferenceClickListener(new OnPreferenceClickListener()
    {
        public boolean onPreferenceClick(Preference pref)
        {           

            resetSettings(SettingsFragment.this.getActivity());


            return true;
        }
    });
}

And use it after the

setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);
addMyResetListener();

So `resetSettings` changes to

 public void resetSettings(Context ctx) // also removed static
 {

    PreferenceManager
    .getDefaultSharedPreferences(ctx)
    .edit()
    .clear()
    .commit();
    PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true);           

    setPreferenceScreen(null);
    addPreferencesFromResource(R.xml.preferences);   
    addMyResetListener();
 }

That way you do not need a custom preference `ResetPreference`

Problem

I'm implementing a custom `Preference` that shall behave similar to a button (the preference will open up a dialog for restoring the default values of all preferences). It's working fine if you click on the `ResetPreference` the dialog shows and on positive click all preference data is cleared and reset, but if you click on the `ResetPreference` again nothing happens. I suppose that while setting the `PreferenceScreen` to null and re-adding the resources something is amiss. If you ask why I used this approach, I wanted to click on reset and directly show the result of the change, if anyone knows a better way to implement a reset please give a little example. PS: If clicking on the `ResetPreference` and selecting the negative button nothing happens and the listener is still functional so it should really have something to to with deleting and re-adding the resources. ResetPreference.java ``` public class ResetPreference extends Preference { public ResetPreference(Context context, AttributeSet attrs) { super(context, attrs); setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.prefAlertDialog_Title); builder.setMessage(R.string.prefAlertDialog_Message); builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { SettingsFragment.resetSettings(getContext()); } }); builder.setNegativeButton(R.string.prefAlertDialog_Negative, null); builder.create().show(); return false; } }); }} ``` Then there is my custom PreferenceFragment SettingsFragment.java ``` public class SettingsFragment extends PreferenceFragment{ private static SettingsFragment sf = null; public static void resetSettings(Context ctx) { PreferenceManager .getDefaultSharedPreferences(ctx) .edit() .clear() .commit(); PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true); if(sf != null) { sf.setPreferenceScreen(null); sf.addPreferencesFromResource(R.xml.preferences); } } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sf = this; // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); Preference reset = (Preference) findPreference("reset"); reset.setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.prefAlertDialog_Title); builder.setMessage(R.string.prefAlertDialog_Message); builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { PreferenceManager .getDefaultSharedPreferences(getActivity().getApplicationContext()) .edit() .clear() .commit(); PreferenceManager.setDefaultValues(getActivity().getApplicationContext(), R.xml.preferences, true); setPreferenceScreen(null); addPreferencesFromResource(R.xml.preferences); } }); builder.setNegativeButton(R.string.prefAlertDialog_Negative, null); builder.create().show(); return true; } }); } @Override public void onStop() { super.onStop(); sf = null; }} ``` After adding the suggestion from https://stackoverflow.com/a/24648780/3387852 everything is done in the `SettingsFragment`. The `ResetPreference` is no longer needed and the standard android `Preference` can be used instead. The only code needed to implement the reset button is in this updated SettingsFragment.java ``` public class SettingsFragment extends PreferenceFragment{ private void addMyResetListener() { Preference reset = (Preference) findPreference("reset"); reset.setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.prefAlertDialog_Title); builder.setMessage(R.string.prefAlertDialog_Message); builder.setPositiveButton(R.string.prefAlertDialog_Positive, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { resetSettings(SettingsFragment.this.getActivity()); } }); builder.setNegativeButton(R.string.prefAlertDialog_Negative, null); builder.create().show(); return true; } }); } public void resetSettings(Context ctx) { //Remove all Settings PreferenceManager .getDefaultSharedPreferences(ctx) .edit() .clear() .commit(); //All Settings that are empty will be loaded from default values again PreferenceManager.setDefaultValues(ctx, R.xml.preferences, true); setPreferenceScreen(null); addPreferencesFromResource(R.xml.preferences); addMyResetListener(); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource & add listener addPreferencesFromResource(R.xml.preferences); addMyResetListener(); } } ```

Original source