How to Pass Application Context within Singleton and SharedPreferences Classes

10,046

Solution 1

Never use static references to Context in Android, this will cause you an important memory leak since Context has references to all the application resources.

Most of the Android UI classes have a dynamic reference to the context, in fragments you can do getActivity(), in views getContext() consider using those instead of context singletons

More information about this here

Solution 2

While Guillermo Merino concern is valid, an application Context used in a singleton class should not be automatically considered a memory leak.

Calling context.getApplicationContext() will, regardless of where or how it is accessed, always return the same instance from within your process. It will be "alive" for at least as long as the singleton will, therefore holding a reference to it should do no harm.

That said, it might not be enough to perform certain operations, as Dave Smith describes in his blog post.

Since OP is trying to access default SharedPreferences, this could be achieved using just application Context, e.g.:

// Custom Application class.
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        SingletonClass.INSTANCE.init(getApplicationContext());
    }
}

// Singleton.
public enum SingletonClass {
    INSTANCE;

    private Context applicationContext;

    public static int fontSizeMin = 17;
    public static int fontSizeMax = 35;

    public static final String keySelVerseFromList = "keySelVerseFromList";
    public static final String keyFavVerses = "keyFavVerses";
    public static final String keyListOfVerses = "keyListOfVerses";
    public static final String keyIsFavSelected = "keyIsFavSelected";

    // Make sure you only call this once - from MyApplication.
    public void init(final Context context) {
        applicationContext = context.getApplicationContext();
    }

    public Context getApplicationContext() {
        if (null == applicationContext) {
            throw new IllegalStateException("have you called init(context)?");
        }

        return applicationContext;
    }

}

I don't believe this would cause any memory leaks, but if I'm mistaken, please do correct me.

Share:
10,046
user2011302
Author by

user2011302

Updated on June 04, 2022

Comments

  • user2011302
    user2011302 almost 2 years

    How to pass application context from Singleton class to SharedPreferences? I have a fragment and a GridView inside its onActivityCreated(Bundle savedInstanceState) method , on item-click, I am getting NullPointerException in logcat:

    03-30 05:12:54.784: E/AndroidRuntime(1950): FATAL EXCEPTION: main
    03-30 05:12:54.784: E/AndroidRuntime(1950): java.lang.NullPointerException
    03-30 05:12:54.784: E/AndroidRuntime(1950):     at android.preference.PreferenceManager.getDefaultSharedPreferencesName(PreferenceManager.java:374)
    03-30 05:12:54.784: E/AndroidRuntime(1950):     at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:369)
    03-30 05:12:54.784: E/AndroidRuntime(1950):     at com.example.duaapp.utility.SharedPreferencesSupplication.save(SharedPreferencesSupplication.java:35)
    

    Singleton Class

    public class SingletonClass {
    
        public static Context applicationContext;
    
        public static int fontSizeMin = 17;
        public static int fontSizeMax = 35;
    
    public static final String keySelVerseFromList = "keySelVerseFromList";
        public static final String keyFavVerses = "keyFavVerses";
        public static final String keyListOfVerses = "keyListOfVerses";
    
        public static final String keyIsFavSelected = "keyIsFavSelected";
    
    }
    

    SharedPreferences

      public class SharedPreferencesSupplication {
    
    
            public void save(String valueKey, String value) {
    
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SingletonClass.applicationContext);
                SharedPreferences.Editor edit = prefs.edit();
                edit.putString(valueKey, value);
                edit.commit();
            }
    
            public void save(String valueKey, int value) {
    
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SingletonClass.applicationContext);
                SharedPreferences.Editor edit = prefs.edit();
                edit.putInt(valueKey, value);
                edit.commit();
            }
    
            public void save(String valueKey, boolean value) {
    
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SingletonClass.applicationContext);
                SharedPreferences.Editor edit = prefs.edit();
                edit.putBoolean(valueKey, value);
                edit.commit();
            }
    
            public void save(String valueKey, long value) {
    
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SingletonClass.applicationContext);
                SharedPreferences.Editor edit = prefs.edit();
                edit.putLong(valueKey, value);
                edit.commit();
            }
        }
    

    On gridview_item_Click, whenever new SharedPreferencesSupplication().save(SingletonClass.keyIsFavSelected, false); is called, the app crashes and nullpointer exception is raised in logcat. Where am I going wrong?

  • Kuba Spatny
    Kuba Spatny about 10 years
    Just to add to this: To get shared preferences you need Application Context so I would always pass it in the argument as save(getApplicationContext(), value1, value2);
  • Kuba Spatny
    Kuba Spatny about 10 years
    I think you are right, it's much discussed here stackoverflow.com/questions/987072/…
  • IgorGanapolsky
    IgorGanapolsky over 9 years
    @curtisLoew Why create a separate method in SingletonClass to get application context? You can just create a static method in the Application extended class - MyApplication.
  • IgorGanapolsky
    IgorGanapolsky about 8 years
    How do you call getApplicationContext() from an outside class??
  • user3829751
    user3829751 over 7 years
    Android studio still gives me this lint warning when hovering over INSTANCE: "Do not place Android context classes in static fields (static reference to SingletonClass which has field applicationContext pointing to Context)". Is this something I should be worried about?