Search code examples
androidsingletonlifecycle

Is it necessary to save singletons?


Problem:

I'm saving some data in a singleton class... Sometimes it happens, that this singleton returns null data, from which I derive, that it was destroyed...

My idea/thoughts:

Actually, I thought, the singleton will live as long as the application lives and as long as the application remembers anything else like fragments state for example, my singleton will exist with it's last data too. Isn't this correct?

concrete problem:

My case is following: I go from my main fragment to a sub fragment and save an selected object in my singleton... I stop using my app and come back after some time. My app remembers it's state and recreates the fragments, my fragment want to get the selected object from my singleton and get's null.

I thought, a singleton should exist as long as the application exists and therefore needs no saving... Whenever the application is ended, nothing will be restored anyway and my app won't remember anything, so that's ok anyway. Is that a wrong assumption?

I need an answer to this question, because if I'm sure, that above thoughts are correct, I at least know, that I have to search for the problem somewhere else...


Solution

  • Here is a short summury of what I've found out (or have had forgotten)

    • Activitys can be recreated, although the application was destroyed
    • Singletons can be garbage collected if not referenzed from somewhere

    So you HAVE TO SAVE your singletons! Otherwise, whenever your phone is on low memory, it may kill the application and create a NEW application, but RECREATE the activities...

    For me, as I'm actually always use a single activity with fragments, it is easy to solve the problem:

    • when I create an activity, I call a static restore function (BEFORE calling get!!!)
    • in the onSaveInstanceState of the activity a always save the singleton to the bundle

    => so my singleton looks like following (base structure)

    public class DataCache implements Parcelable
    {
        private static final String TAG = DataCache.class.getName();
        private static DataCache mCache = null;
    
        public static synchronized final DataCache get()
        {
            if (mCache == null)
                mCache = new DataCache();
            return mCache;
        }
    
        private DataCache()
        {
            // init...
        }
    
        public void save(Bundle outState)
        {
            outState.putParcelable(TAG, this);
        }
    
        public static void restore(Bundle savedInstanceState)
        {
            if (savedInstanceState != null && savedInstanceState.containsKey(TAG))
            {
                // only restore, if necessary, i.e. if application was destroyed but activity saved our last cache
                if (mCache == null)
                    mCache = savedInstanceState.getParcelable(TAG);
            }
        }
    }