I have created an ExpandableListAdapter class and I need to send it the context from the activity that is accessing it.
MyActivity.class:
MenuExpandableListAdapter.useInstanceContext(getApplicationContext());
MyExpandableListAdapter.class:
static Context context;
public static void useInstanceContext(Context applicationContext) {
context = applicationContext;
}
The above code works, but this also works:
MenuExpandableListAdapter.useInstanceContext(this.getApplicationContext());
What's the difference? Is this a good way to pass context? I'm still trying to fully understand context.
Context is necessary in order to get access to the resources and some other things. So, both - application and activity contexts work. But a good practice is tight to the smallest thing, which works, which is activity in your case. So, I would suggest new way for you:
MenuExpandableListAdapter.useInstanceContext(this);
Also, in your example, there is no difference between the calls. this is just the reference to the current object.
this refers to the object that is currently executing code, if the method is declared in the same class, and is not static, it is the same to call:
getApplicationContext()
and
this.getApplicationContext()
(The same applies to class members)
MenuExpandableListAdapter.useInstanceContext(getApplicationContext());
The getApplicationContext() method will called by using calling/current object implicitly.
in second you are giving calling/current object explicitly because this is special object that is always refer to calling object.
i suggest you to use this
MenuExpandableListAdapter.useInstanceContext(this.getApplicationContext());
because as per my reading it's good practice.
Related
I was reading about context in Android and were using in my android application.But then a thought came into my mind. That , Why do we pass context in the constructor only and not some method,something like that component.setContext(context),where component is a hypothetical component and setContext is a hypothetical method and context could be getConetxt/this/getApplicationContext(upon the requirements).
if anyone thinks that title or anything is not appropriate,they are free to change/edit.
Please help me to understand it.Thanks
Basically both are same, if you pass a Context via constructor or via any setter method.
You will still have to have a reference to the Context in your class which will either be initialized during the creation of the object, that is via the constructor or will be initialized later via any setter method.
In both the cases, the Context reference is still there. It is just a question about eager initialization or lazy initialization.
But in case of eager initialization, while accessing the Context in the class you are sure that the context has been initialized for sure and you can safely use it.
But there is no guarantee for that in case of lazy initialization. And as a size note do check out the difference about the two types of Context - Application context and Activity context.
In my last project in the activities I had a lot of MyActivity.this provided to the methods requiring context, so I decided to make it like this in the beginning of the class
private Context context = ActivityStage2.this;
and then just pass context to object methods. So far it works ok, but is it ok at all to declare the Context like that? I mean does that always have the updated state of the MyActivity.this each time the context object is referenced?
You can do it but there is no point in doing it.
You basically "cache" the this reference to a field. The field initialization will run just before the constructor body, so every time the object is recreated the reference context will be updated. This works similarly to this, which points at this instance object.
Now why would you do that? Readability? It seems like you want to use it in inner classes, because you explicitly qualify it with: ActivityStage2.this. The java way to qualify the outer class reference from an inner class is well understood by programmers, and here the gain is little. One exception could be anonymous inner classes where you don't have the name of the inner class. In this case caching the reference to the Activity makes sense, but I'd rather use a final local variable instead of a field.
Another reason for doing this could be that you need only the Context interface instead of the ActivityStage2 interface: that makes sense theoretically but in practice I wouldn't do it without some other better reason.
Last thing: if you turn your field in a static one, you will indeed leak.
There is no problem to do this if you follow the two rules listed bellow:
Keep the reference in a instance member. If you use a static field, your Activity instance could never be recycled by the GC because your MainActivity class has a strong reference to the object. If you really need to do this, use a WeakReference.
Keep a reference to your Activity instance. Do not keep a reference to other activity due to the reasons I have just described above.
Otherwise it all depends on you and your code style :)
Somewhere in the application, I need to get a localized string using the getString method for an error message. For this, I need a Context instance, gotten from for example an Activity. Is this really how this is designed? Am I really forced to pass around these objects into classes and methods or am I missing the point and is there some other way to get a string reference?
To clarify, in an Activity I have an inner AsyncTask subclass that in doInBackground instantiates a new class for some short network processing outside the UI thread. I want error messages to be localized and for that I need to pass in a Context instance (in other words, the Activity) into that class. The design of getting value resources from the XML files just seems to be a bit unintuitive. It makes me wonder why this is so coupled together with Context instances and not something static or - forgive me - a singleton, as Context implies to be the global application context and not just a part of it like an Activity.
No, you should not do this. A simple rule is; if what you need the context for is touching the UI or is only associated with the internals of the activity class, then you should use the activity context. Even then, it is important that any reference to the context does not have a lifetime which is greater than that of the activity.
The big danger of not following this is that you pass out a reference to the activity context to somewhere deeper in your code and your activity is destroyed whilst the reference you are holding is still in scope. You just leaked your activity and everything it has a reference to. I would recommend not passing the activity context outside the activity unless truly essential and even then, be very sure to control that life time.
So, it the context is needed for something which is not UI related, such as your need to get a string resource, then use the application context. Inside an activity, and where the string reference is declared in the activity, then using the activity context would be acceptable and in my opinion, preferred as you are making a conscious decision regarding scope and life time.
That said, you should ask whether this particular method is better placed in an activity. It may well not be but do ask yourself.
Finally, a small pedantic point. You do not pass objects anywhere. You pass a reference, in fact a value of a reference to the object. Everything in Java is passed by value.
You could always extend the application class. Make a static method on there for getInstace() to get the context.
In some places we were giving like "DatabaseUtil db=new DatabaseUtil(DailyPlanView.this);" where DatabaseUtil is the class with the constructor argument is context. But if we create the object for the DatabaseUtil class in the DailyPlanVIew class we are using the above code. My doubt is what is the use of the context and instead of passing the context object as argument why we are passing "this".
Whenever you are dealing with Context, its important to understand its used in everything. From using a database to obtaining system services. This is required by the way android works with Context. Specifically when you are passing this you are basically passing the class that encapsulates this statement.
class MyActivity extends Activity
{
onCreate(Bundle bundle)
{
View v = new View(this);
}
}
passing this refers to the object that encapsulates it. This is a Object oriented concept... Where this is reffering to MyActivity. One thing to keep in mind when passing context is ensure that you are passing the correct kind. Some Context objects have a longer lifespan than others and if not managed properly can lead to Context leaking. Specifically in this example, this works because Activity extends Context.
The differences occur in the View class.
getApplicationContext()
getBaseContext()
this, which in the Context of an activity has the life span of an Activity (Example above)
One thing to add about Context is that it is basically a reference to the current Application and it's specific data.
Some more information about context can be found in this thread:
What is 'Context' on Android?
I have some classes within my application that need to call Android functions that require the Context as a parameter.
I don't have it as the class is not a subclass of the Activity class.
What is the correct way to tackle this problem?
Pass it as a parameter on each call?
Pass it at class instantiation and keep it?
It depends on the role of the class. But anyway pass ApplicationContext but not Activity one. If you pass Activity context gc can't remove it from the memory when after you don't need activity anymore. But application context is used while application was not finished by OS.Refer Avoid Memory Leaks
Pass it as a parameter. Or better yet, get the application context to avoid memory leaks.
public class Example {
protected Context context;
public Example(Context context){
this.context = context.getApplicationContext();
}
}
I'm pretty much always going with a constructor parameter approach. I pass it in the instantiation and keep a private reference in the instantiated class.
You have to think about one important thing. If the class you pass the Context will exist longer than the Activity instantiating it then you should use the application context. If that class is doing UI stuff you will need an activity context.
Make sure that the class you are passing an activity context to won't last longer than the Activity or you'll leak the entire activity.
If you don't do UI stuff then go with the application context.
I pass it as a parameter, i think its de best form to do it
Pass it at class instantiation and keep it.
One typical example is when you create a db helper. See this link
I've answered this question here also.
You can do that using ContextWrapper, as described here.
For example:
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
}
and use that class as it were Context
The best way is to follow Bean approach:
public class Example {
protected Context getContext() {
...
}
...
}
Then it depends on possibilities to access context. If class is fully independent then constructor parameter and private field seems best approach.
But that bean property way shields you from further code changes.