Is it wise to get a reference to a Context object in every Activity where I need a Context by getting the Application context? I have learned that it can create memory leaks to throw around your Activity's context object but when you create complex Activities it seems that a Context object is almost always necessary. I was previously declaring a Context variable at the top of the Activity class and initializing it with the "this" keyword in onCreate. I already know this can be poor form, but is it ok to initialize the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
There is really no need of a Context field in your Activity, as you can always get the context using getBaseContext(), getApplicationContext(), or this (since Activity itself is Context).
You might have to pass your Context to other classes if you want to keep you Activity class thin. This is perfectly ok as long as the lifecycle of those classes is the same as the lifecycle of your Activity. This means, when your Activity is destroyed, no objects should have the reference to the context you passed.
Static methods are extremely good as long as they don't refer to static fields. Use static methods if they don't have a state. Static fields are dangerous for a lot of reasons. So use them only for the right scenarios.
I think you need to understand the differences between Application Context and Activity Context, please refer to the answer here.
But is it ok to initialise the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Why do you need to initialise a context object? Activity itself is already a context. For example:
Intent intent = new Intent(this, MainActivity.class);
You don't need to initialise a context from application context as the activity context has more capabilities. Please refer to this link.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
For sending a data from one activity to another activity, you might need parcelable object and bundle, or Event Bus to decouple both sender/receiver activity.
For static method, you might need to group them under a Utility class.
Related
While working with different activities and starting them for results I have no choice but to use intent. Now intent requires context and that makes no sense to me. I know that context allows access to the application resources but
why do you need to know about the application resources when an intent is just a simple messenger?
Also, I am not so sure why some people create intent with the getApplicationContext() while other use this for the activity context????
Lastly, I am not so sure how the activity that calls for startActivityResult() receive a call back on the method onActivityResult() when I don't pass the "this" for the context but instead the application context. I thought that you have to use the "this" or passing in the current activity context that called startActivityResult() in order to receive a callback. That is just straight up java right? If you pass in a class then the other activity class will have a reference to your class and hence allows it to call the method in your class which is onActivityForResult(). However, this is not the case so what am I missing?
Intent itself does not need the Context. The constructor Intent#Intent(Context, Class) is just a convenience constructor, that internally uses the provided arguments to derive a ComponentName. ComponentName is in turn just a package name of your app and a class name to target. So ComponentName might be something like:
com.foo.bar/com.foo.bar.ui.activity.MyActivity
However, you can as well just use an empty constructor Intent#Intent() and provide ComponentName yourself (Intent#setComponentName(ComponentName)).
Therefore it doesn't matter if you provide your Application's or your Activity's context (the latter is just simpler to type). Also keep in mind that classes that require application context can call Context#getApplicationContext themselves, so this is not something you need to worry about.
About startActivityForResult() - Android manages internally a stack of your Activity records. Therefore it delivers the result to the previous Activity on the stack. It is the same way it knows where to return, when you click "back".
Please note it doesn't mean it maintains a stack of your Activity instances. These instances might be long gone - destroyed and garbage collected to free the memory. However the stack contains the information that allows to recreate them and to restore their state.
Intent does not need Context for itself but as you yourself pointed out that Intent is just a messenger. It also passes the current state of application/object to the newly created object so that it can understand that what exactly is going on in the application. And that is why we need to pass the context.
And, I believe that you want to ask about startActivityForResult(). Android itself takes care of the callback in the same way other callbacks are handled. You can take the example of Activity Life-cycle. Whenever it is started onCreate(), onStart(), onResume() are called itself by Android.
Not been much deep into Android development but still let me try with an explanation. So basically, context is a reference to linking your resources to your program. Each object is given its own context, which contains the resources required to set that object up. It is required for many objects to be created, and to get program identifying information, among other purposes. This makes it invaluable to set up new views and activities, but it can also be used for other purposes. See this Android Context for more information.
According to this page Activity inherits context. Thus, if you are in an activity, you only need to pass itself to use the context. It also contains a pointer to getBaseContext(). You might occasionally need to reference that, if you need the entire application context, but most likely you won't for a while.
There are ways of creating an Intent which do not require a Context. But if you want to target a specific class of a specific package, then providing a context for the target package is a ready way to do that. Refer this Context Lesson.
As explained by snctin in his answer getApplicationContext() offers application context. Basically the Application context is associated with the Application and will always be the same throughout the life cycle of your app. Also refer this post.
See Android - How to start (display) a new Activity. According to it
startActivity(new Intent(this, ProjectsActivity.class));
assumes your current class extends one of the Android Activity classes, which gives you access to the startActivity method.
According to Getting result from a activity, Starting another activity doesn't have to be one-way. You can also start another activity and receive a result back. To receive a result, call startActivityForResult() (instead of startActivity()).
For example, your app can start a camera app and receive the captured photo as a result. Or, you might start the People app in order for the user to select a contact and you'll receive the contact details as a result. This post will help you understand the same more better way.
Hope that helps. And also thanks becuase of your question I had a refresh with Android.:)
I often have the Problem, that I cannot use something because of the Context it needs.
For example, if you have a Toast you want to use in a Class for something, you need Context but you cannot use any context, because you are not in an Activity.
Now what I did was, I gave that Class I made a variable "context" which is set in the constructor, but I don't really think this is right.
So how do I handle the context in a non-Activity Class?
Thanks in advance :)
Never keep a reference to context as a member variable or as a static variable, as it might lead to memory leaks as it becomes difficult for the GC to collect the references.
Since you are using context in a non activity class, I assume that class to be some kind of a helper class with static method blocks.
For eg :
public class ToastMessageHelper {
public static void showToast(Context context) {
Toast.makeText(context, "Hello",Toast.LENGTH_SHORT).show();
}
}
It is better to pass context as a parameter to the methods which require the context to execute.
Now, you can simply call,
ToastMessageHelper.showToast(context);
in your activity or a fragment. Hope this helps!
If you aren't in an activity, you can always use getApplicationContext() which will return the context for the app.
Yes you are right, you usually pass the Context to the required object or class which may require it, sometimes you pass it in the constructor, but knowing that the context may change sometimes is better to pass it right in the method. It is up to the developer choose the right scenario.
It is true that in some situations you could need another way to get or pass the context, but usually passing it in the constructor or methods is enough
A sophisticated way to use context in a non-Activity class is the ContextWrapper.
You can read a little bit about this here:
Best practice to pass Context to non-activity classes?
or here
http://itekblog.com/android-context-in-non-activity-class/
You could also use a variable "context" or pass by parameter in a static method and you should be fine, being in mind you can have some issues with this practice.
I've looked around but never found a straightforward answer to this question. I'm wondering what would happen if I use a pattern that requires me to pass a Context to static methods to do things on the backend. For instance:
public static Observable<CreateThing> createNewThing(String thingName, Context context) { // Passing Context in
return RestNetworker.handleResponse(ServiceGenerator.createService(Service.class).createThing(thingName))
.doOnNext(response -> DatabaseHelper.getInstance(context).createThing(new Thing(response.getThingId(), thingName))); // context used to get instance of DatabaseHelper
}
This method makes an API call and then writes the object to the database locally after a success response. However, I need to pass a Context to create the instance of the database helper. I could alternatively pass the database helper itself, but then I'd be creating the instance (rather getting it, since it's singleton) in the Activity code and I'd rather not do that either.
My question really is: If, say, a user exits the Activity while the API call is in progress, will this Context instance get GC'd and result in an NPE when the response comes back? I've done this kind of thing before and never noticed that issue, but it really seems that there should be some consequence of doing this. I know that other developers must do some things off the UI thread that require a Context, so this should be a relatively easy question to answer.
Thanks guys! Please let me know if you need any more information to provide better context. Heh.
The rule is that you do not pass an instance of the Activity to some object that may keep a reference to it outside of the lifecycle of the Activity. This will cause a memory leak, as the GC will not be able to free the memory allocated to the Activity and the entire view tree contained within. In those instances you pass getApplicationContext().
In cases where the context will only be referenced for the duration of the method call, passing the Activity as this is fine.
In your case, it seems like DatabaseHelper may store a reference to the context, so I would use getApplicationContext() Note that you would not get NPE because the reference was GC if you passed an Activity, that doesn't make sense - if the DatabaseHelper was storing a strong reference, this could not occur (at least on the reference to the Activity itself).
Created java class DBOperations i android project to realize database operations but found that some operations need Context object. Couldn't get it with this or getapplicationcontext method. I decided to pass context object as a paramether,e.g.
Mymdhod(this);
Is it correct way or there are other methods to get application context?
If all things you need the context for can be done in the constructor, consider passing the context as a parameter to the constructor and immediately initialize everything you need the context for.
Otherwise, if you need the context in a public method, pass the context as a parameter to this method.
What you shouldn't be doing is keeping a reference to the context as a member variable. The reference you are holding might be invalidated upon traversal through the activity lifecycle and holding the reference might cause memory leaks as further described in this article.
Yeah, if you need the context in your own classes, the best way is to pass it in like you are doing.
Using parameters of the method calls , you can pass the context of activity and use them in another classes.
For instance:
Obj.methodName(context)
And method
public methodName(Context context){
// do something with context
}
I have a few singletons that require context information as they might have to show dialogs. Up until now I've passed the relevant contexts to the singletons, but this is increasingly leading to memory leaks. I was wondering whether storing a reference to the current activity inside the application class might be a way around this problem. Since the variable is overwritten everytime a new activity starts it shouldn't lead to a memory leak, but it's also accessible from all non-activity classes in the app.
Inside my application class:
private static Activity currentForegroundActivity;
public static void setCurrentlyVisibleActivity(Activity activity) {
currentForegroundActivity = activity;
}
public static Activity getCurrentlyVisibleActivity() {
return currentForegroundActivity;
}
Inside every activity:
#Override
public void onResume() {
super.onResume();
App.setCurrentlyVisibleActivity(this);
Inside every singleton:
methodThatRequiresUI(App.getCurrentlyVisibleActivity);
Are there any pitfalls going down this route that you can foresee? I suppose the application class might be cleared from memory by the OS, but if that happened the app itself would restart - it wouldn't lead to a null pointer. The get method might also get called during application startup before the set had been called - but I can write checks to get around that.
Completely avoid using activity context to a singleton object
that.(yeah you know this)
Dont inflate views, dialogs from app context. It will work but it
will exclude styling and other stuff.
Then how?
make utility methods with static methods, pass context as
parameter.
Use delegation (pass anonymous classes, or an
interface)