I am using several SharedPreferences to store data in my app.
Some preferences are used in a lot of activites.
I know that the SharedPreferences are internally backed by a map for fast read-access and written to sdcard when settings are changed.
I wonder which way is better if a sharedpreference is accessed by a lot of activies:
Instantiate it in every activity using the activity context.
Instantiate it in every activity, but using the application context.
Put it in e.g. the Application class and instantiate it only once there, similar to a singleton.
If I use 1. solution is there a sharedpreference object for every activity? And will the sharedpreference's internal map get destroyed when the activity is destroyed?
If I use 2. solution will there be only one instance although I call getSharedPreferences in every activity? And will the internal map be in memory as long as the application is alive?
Hopefully someone knows how Android handles it internally.
It is worth reviewing the sources that show that a Context instance (be it an Activity or an Application instance) share the same static map HashMap<String, SharedPreferencesImpl>.
So whenever you request an instance of SharedPreferences by the same name via Context.getSharedPreferences(name, mode) you get the same instance since it first checks if the map already contains SharedPreferences instance for a key (which is the passed name). Once SharedPreferences instance is loaded it will not be loaded again, but taken from the map instead.
So it actually does not matter which way you go, the important thing is to use the same name in order to get the same prefs from different parts of the application. However creating a single "access point" for the prefs could be a plus. So it could be a singleton wrapper over the prefs instantiated in Application.onCreate().
SharedPreferences are managed internally by Android as singletons. You can get as many instances as you want using:
context.getSharedPreferences(name, mode);
as long as you use the same name, you'll always get the same instance. Therefore there are no concurrency problems.
I will prefer using a singleton class for preference, initialize preference once by application context. create getter and setter(get/put) methods to add, update and delete data.
This way it will create instance once and can be more readable,reusable.
We can make a Preferences Singleton Class and make instance of that class in extended Application class with applicationContext, so we may use that object in whole application
I have made a sharedPreferenceManager Class and make a static object by providing applicationContext. Now static object can be accessible anywhere in project
public class App extends Application {
public static App myApp;
public static PreferenceManagerSignlton preferenceManagerSingleton;
#Override
public void onCreate() {
super.onCreate();
myApp = this;
preferenceManagerSingleton = new PreferenceManagerSignlton();
preferenceSingleton.initialize(getApplicationContext());
}
}
Accessing static object in project
App.myapp.PreferenceManagerSignltonz.getSavedValue();
Related
I try to use SharedPreferences, but I don't understand why we need the context.
If I create a SharedPreferences with the context of my main activity, can I get something with another context?
For example with an intentService class
Thanks
An IntentService is a subclass of Context (just as are Activity, Application, and many other Android classes). So of course you can create a SharedPreferences from an IntentService. It will see the same SharedPreferences values that any Activity or other Context in your application would see. (That's why it's called shared.) You just have to make sure that you apply() or commit() changes made in the preference's editor in one context for the changes to be seen in other places. This is all covered in the docs.
The SharedPreferences are read and saved to disk.
Therefore the class needs to know where the app is located - and the only way to know that is thru a Context.
In standard Java there are global (static) objects, so you can do like for example System.getProperty("user.home") to access the user's home directory. That systems isnt maintained in Android - in Android you need to use the Context to get to the home dir of the app
Yes, This is non sense question,but anyway.
As you know about SharedPreference.It is used to Store private primitive data.
Here,on private data term. This means this data is stored to your application's storage path. Which is data/data/yourpackageName/shared_prefs.
So To access your application's storage, SharePreference needs your active context of any running Activity.
Looking at the Android Source Code. You would get to know that Context class internally maintains a static HashMap of shared preferences for quick access:
private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
new HashMap<String, SharedPreferencesImpl>();
So you can get SharedPreferences from any class like Intent Service or Activity etc which extends Context and it will always return the same object if given the same name.
Note: IntentService does extend Context if you trace the chain:
IntentService extends Service
Service extends ContextWrapper
ContextWrapper extends Context
I want to have my application preferences accessible in every activity. I don't want to have to get all of the SharedPreferences in every activity. but instead get SharedPreferences once, and have a global object that has values for all these preferences, like if (AppSettings.isSoundOn()) {// do stuff} and have that object available everywhere with no ifs and buts.
I tried using static classes but you can't get Shared Preferences from a static class. Also it looks like that the class you get SharedPreferences in has to extend Activity, or it produces an error.
I'm sure there is a stupidly simple way this is usually done, as it is basic app functionality, but none of the Android development books I have actually covers how to deal with application wide preferences, and any tutorials I could find just cover setting and getting SharedPreferences which is simple, but you have to do it in every activity.
Create a class like MyApplication and extends from android.app.Application.
In there you can access the sharedpreferences.
In every Activity you can get the Application by using MyApplication app = (MyApplication)this.getApplication();
In MyApplication put a public method that gets the Sharedpreference and one that stores it.
An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android
What exactly is the purpose of Application class.
what are the benefits of extending it to a custom subclass
Why use it ?
Can global variables be stored in any other class achieve same goal as Application ?
Nice question !
Your application is a context that is always running while your activities and services are running.
It is also the first context to be created and the last to be destroyed.
Thus, it surrounds the life cycle of your app.
You can use the application class as a way to share data or components (for dependency injection for instance). For instance if you want to share a singleton between activities, you can create the instance in the application class and provide a getter, then all other contexts can get the singleton via
((cast to your class)getApplicationContext()).getFoo();
There may be some use cases where you need to do stuff before even your first activity is launched, then do it in the onCreate method of the application class.
On the other hand, you should never relie on the onDestroy method of the Application class, as it is not always called. There is no contract for that on Android.
But this is rare and, usually, you don't need to override the application class though. Dependency injection can be achieved in other ways by RoboGuice or Dagger for instance.
Two things makes this Class very useful:
Application class is instantiated before any other Activity.
It holds the Application Context
Context brings a host of resources for us: we can figure out some device properties, load some resources, initiate a SQLite database etc, etc.
All of this happens before any Activity loads, and all of this is globally available to the Activities.
Simple example of what I mean:
public class App extends Application{
private static Resources sResources;
//--I want to load strings resources from anywhere--
public static String loadStringResource(int resID) {
return sResources.getString(resID);
}
#Override
public void onCreate() {
super.onCreate();
sResources = getResources();
//---I want to load all preferences when my app starts---
PreferenceManager.setDefaultValues(this,R.xml.prefs,false);
}
}
Extending the Application class allows you to integrate into the application's lifecycle.
This is also useful to store global application-level information (though it's usually good to keep your activities 'independent')
The Application class is aware of the Application Context and is loaded when your app is loaded so it holds the proper callbacks for the application lifecycle before your activity starts. You most likely would not want to extend this class.
From the API docs:
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
I declared a non-final static SharedPreferences object called PREFS together with the other constants in my Constants.java class:
public static SharedPreferences PREFS = null;
My reason for doing so is that my app is comprised of about 6 different AsyncTasks that keep accessing the same shared prefs file, and I didn't want to get the SharedPreferences and its Editor every time. On my app's first run, I make a call to getSharedPreferences() in my MainActivity and store it to PREFS so that it points to an instance before the AsyncTasks are fired, and therefore avoid a NullPointerException.
However, I kept getting NullPointerExceptions from the AsyncTasks anyway. All stack traces point to the line where I make a call to Constants.PREFS to get a value. My theory is that after some time, Android kills my app's process, so the next time the alarm for any of my AsyncTasks goes off, the value of Constants.PREFS would already be null.
My question is: Should I make a static variable for Context instead? Will its state be persisted even when Android kills off my process? I always pass a reference of Context to my AsyncTasks when the latter are instantiated so they can call on getSystemService(), and that never throws a NullPointerException. However, I don't see Context extending Serializable from the Android docs.
Use Application class to share preferences globally across the application.
public class MyApp extends Application {
private static Context mAppContext;
#Override
public void onCreate() {
super.onCreate();
mAppContext = getApplicationContext();
}
public static SharedPreferences getPreferences(){
return mAppContext.getSharedPreferences("my_app_preferences",MODE_MULTI_PROCESS);
}
}
Tell android you want your custom Application class, by mentioning it in the manifest:
<application android:name=".MyApp" android:label="#string/app_name" android:icon="#drawable/ic_launcher">
Now from anywhere, just call
MyApp.getPreferences().edit().putBoolean("pref1",true). . . put more stuff . .commit()
MODE_MULTI_PROCESS ensures all AsyncTask threads get synchronized access to same instance of SharedPreferences. Also, commit() is atomic, and will persist changes to the disk.
The above pattern is also handy for accessing resources from anywhere.
Update
It seems that static reference to context causes troubles with new Instant Run feature.
Hence, the context can be required as a parameter of utility method:
public static SharedPreferences getPreferences(context){
return context.getSharedPreferences("my_app_preferences",MODE_MULTI_PROCESS);
}