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.
Related
Hey I'm using Android Studio with Kotlin and I have an activity and a service that both needs to call same methods, so I created an object with theses methods in it, which would be like a utils class.
The problem is that the methods depend on a field that needs the application context to be created, and the only way I found to retrieve the context was to pass it through the constructor, but as it's an object I can't do that.
How could I keep that object behaviour and retrieve the application context ?
In Kotlin, an object behaves like a static util class(not exactly at bytecode level) so there are only a few options that you could do
Pass the the context in every util method in the object which needs the context
Make an Application class and keep a global reference of the application context and use it everywhere by making it lateinit var and initialising it in Application`s onCreate method
Or use DI for injection of Application context and instead of using Object use Singleton scoped utility that is injected everywhere
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.
I have a helper class that I need context so I can access the SharedPrefences. Other posts recommend passing in the application context on instantiation of the helper class. So I made that change, it works very well except within a tab activity. The tab activity need to call a webservice to determine what data to display. The helper class makes the webservice call.
You can call getContext() from any activity. If the helper class is defined as a subclass of the activity, it can call it directly. Otherwise, passing the context through instantiation would be my second choice. I agree, it's not pretty passing contexts everywhere. There are probably some complicated OOP patterns you could use to avoid this, but I can't see it being an advantage overall.
If you get a null pointer you might be calling the function too early. In what function are you calling it?
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.