Unable to fetch SharedPreferences

102 views Asked by At

I'm trying to get familiar with using SharedPreferences, by building a simple test app where I store and retrieve user preferences by using a class that extends 'PreferenceActivity'.

The problem is that every time I shut down the app and start it again I'm unable to load the SharedPreferences values that I earlier selected.

In the MainActivity's onCreate method I am first calling a method 'loadPreferences', then creating an ImageView and a button. I assigned onclick listener to the button that creates and starts a new intent.

...onClick(View v){
    Intent intent = new Intent(MainActivity.this, MyPrefsActivity.class);
    startActivity(intent);
}

In MyPrefsActivity class I have a ListPreference that has a 'Preference.OnPreferenceChangeListener'.

... {
    @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            imageNumber = Integer.parseInt(newValue.toString());
            return true;
        }
    };

Upon return from MyPrefsActivity to MainActivity in the 'onResume':

protected void onResume() {
    super.onResume();
    savePreferences();
    loadPreferences();
}

private void savePreferences(){
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putInt("imageNumber", MyPrefsActivity.imageNumber);
    editor.apply();
}

private void loadPreferences (){
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        int imageNumb = prefs.getInt("imageNumber", 0);                                                       
        switch (imageNumb){
            case 0:
                imageView.setImageResource(R.mipmap.image1);
                break;
            case 1:
                imageView.setImageResource(R.mipmap.image2);
                break;
            case 2:
                imageView.setImageResource(R.mipmap.image3);
                break;
            default:
                imageView.setImageResource(R.mipmap.image4);
        }
}

When 'loadPreferences' is called for the first time upon startup, 'imageNumb' allways has a value 0, instaed of the value that I assigned to on previous run in method 'savePreferences'.

I noticed that after startup when I enter 'MyPreferencesAction' for the first time and open the ListPreferences, the checkbox that I selected on the last run is already selected for me. It seems like my selection is saved but when I try to load SharedPreferences am I messing up something???

2

There are 2 answers

6
Dalija Prasnikar On

You have to save your preferences in onPause event. Right now you are saving it in onResume when values you want are no longer there.

@Override
protected void onPause(){
   super.onPause();
   savePreferences();
}

@Override
protected void onResume() {
    super.onResume();
    loadPreferences();
}

There is another issue with your code. You are saving preferences in MainActivity, but you are changing them in MyPrefsActivity. That will not work. You have to save changes to the preferences in MyPrefsActivity, use above load/save pattern in there too. If you don't have any preference changes happening in MainActivity, you can safely omit calling savePreferences from it.

Depending on MyPrefsActivity declaration calling MyPrefsActivity.imageNumber from MainActivity may not be safe, you will have to change that code too. Like I said, most likely you don't need it at all in MainActivity (if you saving are only preferences values that are set in MyPrefsActivity) and that should be part of MyPrefsActivity.

Also Preference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value.

0
Nabuska On

I realized there was a lot of needless complexity in my code. So I got completely rid of the method savePreferences(). Instead i simplified the PreferenceChangeListeners method onPreferenceChange(...): This seems to me to be the most simplest way to update SharedPreferences when using PreferenceActivity.

public boolean onPreferenceChange(Preference preference, Object newValue) {                
            preference.getEditor().
            putInt("imageNumber", Integer.parseInt(newValue.toString())).apply();
            return true;
        }

Now I save the SharedPreferences manually, only when 'onPreferenceChange' is called. Not on 'onResume', 'onStop', 'onRestart' or on 'onPause'.

Please inform me if this is a bad way to change SharedPreferences.

Quoting Dalija Prasnikar: "reference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value."

If you understood you correctly Dalija, there is a 'onPreferenceChange(...)' like method that does the job but does not have a boolean return value but void? I was not able to find any examples, could you please show or point to an examle?