I have an application which need to access context in a lot of different classes all the time, for saving and serializing data, showing dialogs etc.
According to an article on the Android developer site, this causes memory leaks:
http://developer.android.com/resources/articles/avoiding-memory-leaks.html
What is the general approach for accessing context? Should a create a singelton class which holds one reference to context as soon as the app is started or what's the best approach?
Right now my methods look like this for instance
public void saveData(TheCassName classObject, Context context){
//do some stuff that involves context
}
And is called from wherever i need it.
Thanks!
Just to clear: There is no memory leak as context which is getting saved, is part of the application which is a process which will only get killed when the application will close.
Extend application in your app and then use the application context by
making static variable in that.
public class MyApp extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApp.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApp.context;
}
}
You need to define application also in your manifest too.
<manifest>
<application android:name="com.abc.MyApp">
</application>
</manifest>
Try using application context instead of activity context. However, there are limitations on app context you should be aware of: When to call activity context OR application 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 am noob in Android. I see there are many methods associated to get context either activity or application context. What context you should use in what scenario ??
One blog saying to use the context-application instead of a context-activity to avoid memory leaks. How here memory can be leaked if I use Activity context
Any idea ???
You create one Method that returns Context(this). Parse Activity to Application as below (under Methods defined in MainActivity class):
public Context getContext() {
return getApplicationContext();
}
public Activity getActivity() {
return this;
}
and then use:
Application abc = ((Application)getActivity());
this question is intended to ask to the community if the approach i've taken for my app is correct or may have some side effect:
I've created:
- an Activity, called MasterAcitity, extended from every activity in my app. The application tag in the manifest is declared as follow
<application
android:name="my.package.name.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#style/ApplicationStyle" >
A class, called MyApplication, that extends android.App.Application, which has the following code
private static Context _context;
public static Context getContext() {
return _context;
}
public static void setContext(Context context) {
_context = context;
}
In the manifest the application tag is declared as follow
<application
android:name="my.package.name.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#style/ApplicationStyle" >
MasterActivity executes this code in OnResume and OnCreate methods
MyApplication.setContext(this);
Every activity of the app extends MasterActivity.
There is a class in the app, called DialogHelper which has a static method
public static void showDialog(String message)
which uses android.app.AlertDialog.Builder to create and show a dialog using as context MyApplication.getContext()
so from everywhere in my app i can use
DialogHelper.showDialog("my message");
Is this approach going to work? or i need to pay attention to something?
My doubt is on the static context...
Thanks
Is this approach going to work?
Using an Application for UI work has a history of causing problems. Either use an Activity, or a specialized Context for a given set of circumstances (e.g., getThemedContext() on ActionBar, getContext() on a Presentation).
You should also have a onDestroy handler that resets the context to null if the context belongs to the activity beeing destroyed.
Instead of a global static context i would prefer a api like this
DialogHelper.showDialog(this.getContext(),"my message");
[Updated 5.5.2013]
Every Activity, Service , BroadcastReceiver is indirectly derived from Context via ContextWrapper and other classes like Views save and use Context. they normally expose it through a getContext() function. So the context should be available where neccessary.
This might be a simple question but I just wanted to make sure I am right.
In my android application I have a constructor that uses:
activity.getApplicationContext()
The activity is passed into the constructor as a parameter.
The problem is that I am calling this class from a Service. If I make a second constructor which accepts the Service as a parameter and uses service.getApplicationContext? Will I get the same application context?
The easiest way to get the application context is:
Create a class App that extends android.app.Application
public class App extends Application {
public static Context context;
#Override public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
Modify your AndroidManifest.xml 's <application> tag to have the attribute android:name="your.package.name.App".
Any time you need the application context, just get it from App.context.
Application is always initialized first whether your process runs, whether it's an activity, a service, or something else. You will always have access to the application context.
Will I get the same application context?
Yes. You can check the android documentation, they have provided
getApplicationContext()
Return the context of the single, global Application object of the current process.
So it should not be changed for the whole application process.
Please also take a note of this:
getApplicationContext() generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.
Correct me if I'm wrong.
Thanks
There is only one application context, so you should get the same one. You can have just one constructor that takes a Context, you don't really need two. Or if you wanted to make sure that you are getting the application context, and not, say, an activity one, you can have your constructor take Application as a parameter which is a Context.
You can go for getApplicationContext() if you wanna get context of whole application. If you want to get context of current class you can use getBaseContext() instead.
I have adapted yuku's answer with a non static direct context reference.
Create a class domain.company.pseudo.ApplicationName which extends android.app.Application.
package hypersoft.systems.android;
import android.app.Application;
public class Starbox extends Application {
public static Starbox instance;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
}
In this sample, my full application package name is hypersoft.systems.android.starbox.
Now, modify your AndroidManifest.xml <application> tag to have the attribute android:name="hypersoft.systems.android.Starbox", and be sure the Starbox.java class file is located in the project component directory: android rather than starbox.
With all this done, you can now import hypersoft.systems.android.Starbox, and in your code you can get the ApplicationContext by calling Starbox.instance.getApplicationContext()
Successfully compiling with build tools 26 and api 26 (Android 8.0) with min sdk version 14 (4.0).
Application Context add Activity Context both are different.Downcasting is risky .Use this code to use context object .
public class App extends Application {
public static Context context;
#Override public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
In Your Activities and in fragments Class :
Conetext context=App.context;
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" >