Avin's Blog

Android Basics: Settings - II

June 28, 2020
Tags: Android, Android Basics, Github Repository App, Settings, Preferences, ListPreference,

All the changes that we make in the activity are reflected in the default SharedPreference. There can be other SharedPreferences, we are going to use the one which is used by default.

You can get the code for everything we have done till now here.

How to listen to changes in Preferences

Overview

  1. Implement the interface SharedPreferences.OnSharedPreferenceChangeListener in the Activity.
  2. Override and fill out the method onSharedPreferenceChanged.
  3. Register and unregister the listener in onCreate and onDestroy.

Implement OnSharedPreferenceChangeListener interface

Add SharedPreferences.OnSharedPreferenceChangeListener to the activity where you want to detect the changes.

public class MainActivity extends AppCompatActivity implements RepositoryAdapter.ListItemClickListener, SharedPreferences.OnSharedPreferenceChangeListener

Override and fill out the method onSharedPreferenceChanged

After adding OnSharedPreferenceChangeListener android studio will be unhappy and show you those red wavy underline because SharedPreferences.OnSharedPreferenceChangeListener is an interface with the method onSharedPreferenceChanged in it, which means we have to override and implement it.

This is where we will add the code that is supposed to run in reaction to the changes in the default sharedPreference.

In our case we want to search Github again with the new sort parameter. I have created a method called searchGithub which checks if the edit text is not empty and runs our AsyncTask again with the new sort parameter.

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Log.d("Key", key);
    if (key.equals(getString(R.string.pref_sort_by_key))){
        searchGithub();
    }

Register and unregister the listener in onCreate and onDestroy.

We need to register and unregister the listener. The best places to do it would be the first lifecycle callback onCreate and the last one onDestroy.

Register in onCreate:

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);

Unregister in onDestory:

@Override
protected void onDestroy() {
    super.onDestroy();
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
    sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}

Now when we change settings and come back to our activity the data in our recycler view gets changed according to the sort we selected.

Show ListPreference option selected as summary.

Right now when we go into the settings we don’t get to see the currently selected option until we click and expand the setting. To improve that we want to add the currently selected option as the summary to the ListPreference.

Here is how I did it:

  1. Go through all the preferences and find ListPreference
  2. If the preference is an instance ListPreference type cast the preference into a ListPreference
  3. Get the currently selected value and set it as the new summary.

After we do the three steps above we soon realize the summary is shown but does not change when we select a different value in the setting. So just like we did earlier we add OnSharedPreferenceChangeListener to our Fragment.

  1. Add SharedPreferences.OnSharedPreferenceChangeListener to the fragment.
  2. Override and fill out the method onSharedPreferenceChanged and update the summary.
  3. Register the listener in onCreate and unregister in onDestroy.
public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.settings_pref);
        updateListPreferenceSummary();
    }

    private void updateListPreferenceSummary() {
        PreferenceScreen preferenceScreen = getPreferenceScreen();
        SharedPreferences preferences = preferenceScreen.getSharedPreferences();
        int count = preferenceScreen.getPreferenceCount();

        for (int i = 0; i < count; i++){
            Preference preference = preferenceScreen.getPreference(i);
            if (preference instanceof ListPreference) {
                String activeValue = preferences.getString(preference.getKey(), null);
                ListPreference listPreference = (ListPreference) preference;
                int index = listPreference.findIndexOfValue(activeValue);
                if (index >= 0){
                    listPreference.setSummary(activeValue);
                }
            }
        }
    }

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

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
}

The Result

app

You can find the code for everything done up till now here.

As always if you find any errors, have feedback or just want to say hi please don’t hesitate to leave a comment below.