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
Related
I've wondering if it's okay to do this: whenever we pass a Context variable around, could we just get a singleton reference from the Application class instead
For example here is a subclass of Application class with a single static variable pointing to its own instance
public class App extends Application {
public static mApp;
#Override
public void onCreate(){
mApp = this;
}
}
Then when we need to pass a Context to a method from somewhere, can we just do
foo(App.mApp);
Isn't it okay to treat Context as an application variable?
Well it depends on the context in which you are using it. Many times a context is meant to keep hold of things until it's lifescope is complete and then allow garbage collection to take back whatever it was owning.
Other times the context needs to be an activity to handle life cycle call backs such as onNewIntent or onActivityResult.
Keeping a static instance in the parent is just a shortcut to avoid having to getApplication() and cast it as your type of application. I typically make a method for MyApplication.getApplication().doSomething which will return it's own reference of itself as opposed to ((MyApplication)getApplication()).doSomething
Just seems cleaner for coding purposes. But I would be very leary of using the application context everywhere you need a context, it will come back to bite you eventually.
But yes you can certainly store yourself as a static variable to be shared, I do it in most applications, but typically for a specific shortcut purpose of clean maintainable code, not for cheating on getting context from various crevices.
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.
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 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();
I have been working with android for a little while now and feel pretty comfortable with the platform, but I have gotten a little confused with the Lifecycle of Context Objects. Looking at the hierarchy it is easy to see that Activity and Service both extend Context, and while this is convenient, it is concerning. I have avoided making helper classes that need a shared resource have a static field holding a context (since just about all resources come through some interaction with a Context object) so that way when an activity is destroyed, the GC is free to free it at any time, but I am wondering about resources fetched from a Context.
For example, if I have a static field that holds a File inside of a class. Then make this class's constructor take the current context and assign the File a File resource fetched through the Context passed in, the do nothing else with the Context in my 2ndary class, am I still holding on in some way to the Context?
class testClass{
private static File someFile;
public testClass(Context context){
synchronized(testClass.class){
if(someFile!=null){
//even though I am holding a File, or a SharedPreference Object generated from this context, am I correctly preventing this utility class from holding the Activity object in memory for no reason?
someFile = context.openFileOutput("Some_File.txt", Context.MODE_PRIVATE);
}
}
}
}
I did just read about Context.getApplicationContext() (Sadly not static). It says it returns a context relative to the process and not the activity so if I need to keep a context around, use that one. But the question above still remains.
I remembered I asked this question and thought I would answer it.
Though there may be more kinds of contexts, the primary ones developers use are the Activity Context, and the Application Context (and other things like Service Context). The Activity context is created and destroyed with the activity, so it is not a good idea to use as a constant reference stored between activity creation and destruction. The Application Context doesn't have some of the things an Activity Context has, but everything you would want a static context reference for is there (file IO, preferences...). The application context is also created and destroyed with the application, so you can guarantee that as long as your application code is running, the context is valid.
Because of this, the Application context should be used for things like worker threads that may need a constant access point to a context but not need access to an activity. The best way I have learned to do this is to extend the android Application class. This class is created when the application is created in memory, and as soon as the Application onCreate method is called, the Application Context is valid. This means you can create a static function in your custom application class that gives access to the context.
public class CustomApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
public Context getAppContext() {
return context;
};
}
The only other thing you need to make this work is a modification to your manifest file so android knows to use your application class instead of the default.
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:name=".CustomApplication" >