How to Pass Application Context within Singleton and SharedPreferences Classes
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.
user2011302
Updated on June 04, 2022Comments
-
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 about 10 yearsJust 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 about 10 yearsI think you are right, it's much discussed here stackoverflow.com/questions/987072/…
-
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 about 8 yearsHow do you call
getApplicationContext()
from an outside class?? -
user3829751 over 7 yearsAndroid 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?