4

I have a subscreen:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
  <PreferenceCategory android:title="Hra">
    <PreferenceScreen
        android:key="pref_game_plus_category"
        android:title="@string/operation_plus"
        android:persistent="false">

        <CheckBoxPreference
            android:key="pref_game_operation_plus"
            android:title="@string/pref_title_operation_plus"
            android:defaultValue="true"
        />

I instantiate the Preferences in

public class GamePreferenceActivity extends PreferenceActivity
    implements SharedPreferences.OnSharedPreferenceChangeListener {

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    log.debug("onSharedPreferenceChanged(" + key + ")");
    PreferenceScreen preferenceScreen = getPreferenceScreen();
   ...
        case "pref_game_operation_plus":
            preferenceScreenHelper.setScreenSummary("plus", preferenceScreen, sharedPreferences);

Here I detect a state of the checkbox and set the parent screen subtitle:

public void setScreenSummary(String key, PreferenceScreen preferenceScreen, SharedPreferences sharedPreferences) {
    boolean value = sharedPreferences.getBoolean("pref_game_operation_" + key, true);
    Preference preference = preferenceScreen.findPreference("pref_game_" + key + "_category");
    preference.setSummary(value ? R.string.pref_operation_enabled : R.string.pref_operation_disabled);

When I debug this code, "pref_game_plus_category" has updated its summary but when I return to the root preferences the summary is not changed though.

PS when I restart the preferences activity the summary reflects the current value. It is initialized with:

public void setScreenSummary(String key, Preference preference, SharedPreferences sharedPreferences) {
    boolean value = sharedPreferences.getBoolean("pref_game_operation_" + key, true);
    preference.setSummary(value ? R.string.pref_operation_enabled : R.string.pref_operation_disabled);
}

Update: the summary is update for the first time but subsequent changes (even to different screens) have no effect. It is strange that I can see entry log for this preference twice but debugger is stopped just once. I have to dig into Android sources.

04-23 08:36:46.471 5503-5503/lelisoft.com.lelimath D/l.c.l.a.GamePreferenceActivity: onSharedPreferenceChanged(pref_game_divide_category)
04-23 08:36:48.004 5503-5503/lelisoft.com.lelimath D/l.c.l.a.GamePreferenceActivity: onSharedPreferenceChanged(pref_game_operation_divide)
04-23 08:36:48.006 5503-5503/lelisoft.com.lelimath D/l.c.l.h.PreferenceHelper: pokus
04-23 08:36:48.007 5503-5503/lelisoft.com.lelimath D/l.c.l.a.GamePreferenceActivity: onSharedPreferenceChanged(pref_game_operation_divide)
Leos Literak
  • 8,805
  • 19
  • 81
  • 156
  • Don't know if this is the answer, but SharedPreferences are asynchronous by default, and they do a lot of caching to improve performance (read/write to/from memory instead of disk, that operations is async). The issue may be that when you return to root preferences, it may not have detect that the SharedPreferences has changes and so it's instance is reading from memory rather than from disk. Or, that the disk write hasn't happened yet. I'm not sure how to fix these issues (perhaps close and reopen SharedPreferences?), but it may be worth seeing if my suspicion is correct. – Ali May 02 '16 at 12:49

2 Answers2

3

change your setScreenSummary function to following:

public void setScreenSummary(String key, PreferenceScreen preferenceScreen, SharedPreferences sharedPreferences) {
    boolean value = sharedPreferences.getBoolean("pref_game_operation_" + key, true);
    //instead of getting a reference to preference typecast it to PreferenceScreen
    PreferenceScreen preference = (PreferenceScreen) findPreference("pref_game_" + key + "_category");
    //now set the summary
    preference.setSummary(value ? R.string.pref_operation_enabled : R.string.pref_operation_disabled);

    //here comes the important part
    //get the listView adapter and call notifyDataSetChanged
    //This is necessary to reflect change after coming back from sub-pref screen
    ((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged();

}

I have a demo project on gitlab PreferenceScreenDemo. You can check the whole code. Or you can directly skip to this part of the demo app

Ankit Aggarwal
  • 2,941
  • 2
  • 17
  • 26
1

I notice you are listening for OnSharedPreferenceChangeListener, try to listen for/implement OnPreferenceChangeListener - and then handle

    onPreferenceChange(Preference preference, Object newValue){
    ...
    if(preference.getKey().equals("pref_game_operation_plus")){
       boolean enabled = Boolean.parseBoolean(newValue);
       preference.setSummary(enabled);
    }
   ...
}
ishmaelMakitla
  • 3,784
  • 3
  • 26
  • 32
  • Thank you for hint but unfortunatelly this change had no effect. I rewrote this code, set listener for watched preferences, I can see changes in debugger but they are ignored after second invocation. – Leos Literak Apr 23 '16 at 07:33
  • Did you return `true` in your `onPreferenceChange`? Returning `true` causes the app [to update the state of the Preference with the new value](http://developer.android.com/intl/pt-br/reference/android/preference/Preference.OnPreferenceChangeListener.html). – ishmaelMakitla Apr 23 '16 at 07:54
  • yes I did: case "pref_game_operation_plus": category = preferencesRoot.findPreference("pref_game_divide_category"); category.setSummary("pokus"); log.debug(category.getSummary().toString()); return true; – Leos Literak Apr 23 '16 at 08:27
  • Strange, - but one last thing perhaps, please change `android:persistent="false"` to `android:persistent="true"` OR remote the attribute completely - the default is true. – ishmaelMakitla Apr 23 '16 at 08:47
  • One interesting finding: as long as I change the same screen I can see changes. But when I swap to other screen both sections stop work and no screen summary is not changed anymore. – Leos Literak Apr 23 '16 at 08:55
  • No, persistent attribute has no effect either. – Leos Literak Apr 23 '16 at 08:57
  • Please check the [selected answer here](http://stackoverflow.com/questions/2625246/update-existing-preference-item-in-a-preferenceactivity-upon-returning-from-a-s/5040842#5040842) - they describe how to deal with changes made to sub-screens. [This one](http://stackoverflow.com/questions/4933944/how-to-update-summary-of-preference-from-sub-preference) shows how to use `OnPreferenceClickListener ` - hopefully between these suggestions you can resolve the issue. – ishmaelMakitla Apr 23 '16 at 10:05
  • Please check my answer and let me know if its working or not. – Ankit Aggarwal May 02 '16 at 10:48