Search code examples
androidpreferenceslifecycle

preferences getting lost after app has run for awhile


In my main activity I read some preferences

  public void onCreate(Bundle savedInstanceState) 
  {
      super.onCreate(savedInstanceState);
      SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
      fontSize = settings.getFloat("textsize", (float) 20);
      userName = settings.getString("userName","");
   }

In various other sub-activities I reference these variables like this

            body.setTextSize(Main.fontSize);

This works fine most of the time. Occasionally after the app has been running for a while and I relaunch it, all the configuration variable appear to be empty. It is erratic and hard to reproduce when debugging. When it happens, I can hit back repeatedly through all the old screens until it exits, then relaunch and the preferences are back and working

I could randomly try moving things around into different places like onStart(), or onRestart(), which hasn't helped so far. Or redo every activity to reread the shared preferences when it starts. but I'd prefer to understand what about the lifecycle I've gotten wrong that is causing this problem.


Solution

  • Android regularly destroys your Activity and recreates it when needed. Therefore, your onCreate() function is reading the saved SharedPreferences values, but the class variables fontSize and userName are not staying in scope.

    I believe that the problem seems random and is exasperated because these variables appear to be static. I say this because your example accesses fontSize in a static way:

    body.setTextSize(Main.fontSize); 
    

    You should save the values whenever they are changed or in onPause(), as you probably already do. But, reading them only in onCreate() is not enough because Android is not always going to completely destroy your Activity. So, onCreate() will not be called every time your Activity resumes. You must re-read the values either whenever you need them, or in onResume();.

    I wrote 'exasperated', above, because static variables are not automatically cleared by Java unless the class is completely destroyed. Therefore, sometimes the values will stick around longer than other times making the behavior look unpredictable.


    Finally, it is not best practices to allow these values to be static. There are many other ways to share them between Activites, including SharedPreferences.