SharedPreferences.Editor putString("key", "value").commit() doesn't refresh the currently shown Preferences values until fragment is restarted

Viewed 29

I am trying to have a Prefrence click entry acts like a reset to default button for other preferences shown on the current active preference fragment.

The problem is that using teh Editor to modify a preference will not reflect it on currently active preference screen unless I reload the fragment

In below example, the List contents are not updated, neither the summary. Same for any other preference like a checkbox that I tried

Here's a sample code from Android sample resources that I modified to add the defaults button preference:

MainActivity.java

public final class MainActivity extends AppCompatActivity implements OnPreferenceStartFragmentCallback {
    private static final String TITLE_TAG = "settingsActivityTitle";
    private AppCompatActivity mActivity = null;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mActivity = MainActivity.this;
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.settings, new MainActivity.SettingsFragment()).commit();
        } else {
            mActivity.setTitle(savedInstanceState.getCharSequence(TITLE_TAG));
        }

        getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {
        public void onBackStackChanged() {
            FragmentManager mFrag = getSupportFragmentManager();
            if (mFrag.getBackStackEntryCount() == 0) {
                mActivity.setTitle(R.string.title);
            }
        }
        });
        ActionBar bar = getSupportActionBar();
        if (bar != null) {
            bar.setDisplayHomeAsUpEnabled(true);
        }
    }

    protected void onSaveInstanceState(@NotNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putCharSequence(TITLE_TAG, mActivity.getTitle());
    }

    public boolean onSupportNavigateUp() {
        return getSupportFragmentManager().popBackStackImmediate() || super.onSupportNavigateUp();
    }

    public boolean onPreferenceStartFragment(@NotNull PreferenceFragmentCompat caller, @NotNull Preference pref) {
        Bundle args = pref.getExtras();
        FragmentManager fm = getSupportFragmentManager();
        FragmentFactory ff = fm.getFragmentFactory();
        ClassLoader cl = getClassLoader();
        String frag = pref.getFragment();
        if (frag == null) {
            return false;
        } else {
            Fragment fragment = ff.instantiate(cl, frag);
            //int var7 = false;
            fragment.setArguments(args);
            getSupportFragmentManager().beginTransaction().replace(R.id.settings, fragment).addToBackStack(null).commit();
            mActivity.setTitle(pref.getTitle());
            return true;
        }
    }

    public static final class SettingsFragment extends PreferenceFragmentCompat {
        public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
            setPreferencesFromResource(R.xml.root, rootKey);
        }
    }

    public static final class DialogPreferencesFragment extends PreferenceFragmentCompat {
        private AppCompatActivity mActivity = null;
        private Context mContext = null;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            mActivity = (MainActivity)getActivity();
            mContext = mActivity;

            super.onCreate(savedInstanceState);
        }

        public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
            setPreferencesFromResource(R.xml.dialogs, rootKey);

            SharedPreferences shared_pref = PreferenceManager.getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor pe = shared_pref.edit();

            Preference pref = findPreference("settings_defaults");
            Objects.requireNonNull(pref).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(@NonNull Preference preference) {
                    pe.putString("list", "2").commit();
                    // Force restart of the fragment: for some reason, PreferenceList is not refreshed !!
                    return false;
                }
            });
        }
    }
}


dialogs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <PreferenceCategory
        app:title="@string/dialogs">

        <Preference
            app:key="settings_defaults"
            app:title="Restore defaults in List"/>

        <EditTextPreference
            app:key="edittext"
            app:title="@string/title_edittext_preference"
            app:useSimpleSummaryProvider="true"
            app:dialogTitle="@string/dialog_title_edittext_preference"/>

        <ListPreference
            app:key="list"
            app:title="@string/title_list_preference"
            app:useSimpleSummaryProvider="true"
            app:entries="@array/entries"
            app:entryValues="@array/entry_values"
            app:dialogTitle="@string/dialog_title_list_preference"/>

        <MultiSelectListPreference
            app:key="multi_select_list"
            app:title="@string/title_multi_list_preference"
            app:summary="@string/summary_multi_list_preference"
            app:entries="@array/entries"
            app:entryValues="@array/entry_values"
            app:dialogTitle="@string/dialog_title_multi_list_preference"/>
    </PreferenceCategory>

</PreferenceScreen>

root.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Preference
        app:title="@string/basic_preferences"
        app:summary="Sample preferences using basic attributes"
        app:fragment="com.example.androidx.preference.sample.MainActivity$BasicPreferencesFragment"/>

    <Preference
        app:title="@string/widgets"
        app:summary="Sample preferences with different widgets"
        app:fragment="com.example.androidx.preference.sample.MainActivity$WidgetPreferencesFragment"/>

    <Preference
        app:title="@string/dialogs"
        app:summary="Sample preferences that launch dialogs"
        app:fragment="com.example.androidx.preference.sample.MainActivity$DialogPreferencesFragment"/>

    <Preference
        app:title="@string/advanced_attributes"
        app:summary="Sample preferences with advanced attributes"
        app:fragment="com.example.androidx.preference.sample.MainActivity$AdvancedPreferencesFragment"/>

</PreferenceScreen>

arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="entries">
        <item>Level 1</item>
        <item>Level 2</item>
        <item>Level 3</item>
    </string-array>

    <string-array name="entry_values">
        <item>1</item>
        <item>2</item>
        <item>3</item>
    </string-array>
</resources>

I tried with public static final class DialogPreferencesFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {} and override onSharedPreferenceChanged but obviously it is the same as onSharedPreferenceChanged was not called already on default implementation

However, in onSharedPreferenceChanged override, if I use Preference pref_key then pref_key.setSummary(..), the summary is properly updated

Is there a way to modify other preferences on the same fragment screen and have the contents refreshed without setting a listener to restart the fragment (which I tested and works)

0 Answers
Related