Android list preference view refresh

853 Views Asked by At

I am stuck at a problem where I want to update currently displayed listPreference, in "settings" Fragment of my app, after some code run.

Here's what I am trying to do in steps:

  1. User is shown a settings view
  2. There's a list preference. When he clicks: (2a) Default Entries/values are shown (from xml file) and it's visible (2b) Some code runs in background and write new values to listPreference (list preference view/dialog is still visible). (2c) Now I want to update this view to show new entries

At (2b) above this is what I am doing:

 listPreference = findPreference("mp_key");
 listPreference.setEntries(cs);
 listPreference.setEntryValues(cs);
 //Call on Resume method of the Fragment

Here's what happens. (2a) Default Entries/values are shown (from xml file) and it's visible (2b) Some code runs and write new values to listPreference. list preference view/dialog is still visible. (3a) User "select an item" or "cancel" it, list view disappears and summary is shown (4) When user click on listPreference again, New entries are shown.

//CODE BELOW

public class SettingsActivity extends AppCompatActivity {
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .commit();
    }
}

public class SettingsFragment extends PreferenceFragmentCompat {
    private static ListPreference listPreference;
    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        setPreferencesFromResource(R.xml.preferences, s);
        listPreference = findPreference("mp_key"); //in xml resource, not provided here
        listPreference.setOnPreferenceClickListener(listPrefClickListener);
        }


Preference.OnPreferenceClickListener channelClickListener = new Preference.OnPreferenceClickListener() {
        @Override
        public boolean onPreferenceClick(Preference preference) {
            CharSequence[] cs = listToCharSequence; //test purposes 
            listPreference.setEntries(cs);
            listPreference.setEntryValues(cs);
            return false;
        }
    };
}
2

There are 2 best solutions below

1
tiborK On

I am not sure what do you mean by "Some code runs in background and write new values to listPreference (list preference view/dialog is still visible)" but added one of my settings fragment code that has a checkbox and a list. Hope this will guide you towards your goal.

public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener{

/**
 * creating the preferences
 * @param savedInstanceState saved instance state
 * @param rootKey some key
 */
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    addPreferencesFromResource(R.xml.gl_preferences);

    SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
    PreferenceScreen prefScreen = getPreferenceScreen();

    int count = prefScreen.getPreferenceCount();

    for(int i = 0; i < count; i++){
        Preference p = prefScreen.getPreference(i);
        if(!(p instanceof CheckBoxPreference)){
            String value = sharedPreferences.getString(p.getKey(), "");
            setPreferenceSummary(p, value);
        }
    }
}

/**
 * setting up the summary of the list preference
 * @param preference that needs to have the summary set
 * @param value summary
 */
private void setPreferenceSummary(Preference preference, String value){
    if(preference instanceof ListPreference){
        ListPreference listPreference = (ListPreference)preference;
        int prefIndex = listPreference.findIndexOfValue(value);
        if(prefIndex >= 0){
            listPreference.setSummary(listPreference.getEntries()[prefIndex]);
        }
    }
}

/**
 * Listener when the preferences change
 * @param sharedPreferences that changed
 * @param key that changed
 */
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference preference = findPreference(key);
    if(null != preference) {
        if(!(preference instanceof CheckBoxPreference)){
            String value = sharedPreferences.getString(preference.getKey(), "");
            setPreferenceSummary(preference, value);
        }
    }
}

/**
 * Shared preference created
 * @param savedInstanceState
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

/**
 * cleaning up
 */
@Override
public void onDestroyView() {
    super.onDestroyView();
    getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

}

0
hhs_89 On

I haven't figured it out why exactly why but I think I am not connected to the list view widget to refresh it. I have decided to discard this and moved on with a different strategy.

Thanks to Tibor for input. This is what I do now:

  1. Run my background task in async
  2. Update shared refs on task complete
  3. Show prefs screen