I am using the adapter for ListView/RecycleView on my project. But I am wondering which kind of Context I should pass to the adapter? ApplicationContext or Activity Context(it's mean this on the activity)?.
As I know that the system does not kill the adapter even if the activity being killed. So I have some confusions here:
If I pass the Activity Context to the adapter, so the adapter have an implicit reference to the activity. Can the activity be killed?
In the other hand, I pass ApplicationContext. How long does the Adapter still live? Does it collected by GC after the activity be killed?
Which kind of Context I should pass in specific case?
Thanks,
If I pass the Activity Context to the adapter, so the adapter have an
implicit reference to the activity. Can the activity be killed?
Correction it is an explicit reference since you are passing it manually. So basically the answer to your question is likely YES because the one holding the Adapter is the activity itself, even if the adapter is holding a reference to your activity both of them will be garbage collected once the Activity is finished.
Unless you are dealing with Threads it is recommended to use WeakReference since a Thread can live longer than the activity itself.
In the other hand, I pass ApplicationContext. How long does the
Adapter still live? Does it collected by GC after the activity be
killed?
YES
Which kind of Context I should pass in specific case?
Both can work but Application context is a lot safer.
As I know that the system does not kill the adapter even if the
activity being killed.
Something is not right in the code, probably you are dealing the wrong use of statics or Threads. Additional code required here or a proof of your profiler!
ApplicationContext as it should get cleaned by GC when you destroy the activity if you have more than 1
While using RecyclerView, (which you should prefer to ListView), you most likely will implement RecyclerView.Adapter. One of the methods you have to override there onCreateViewHolder, provides you with the context you should use:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Use this context
Context context = parent.getContext()
}
Related
I have created a singleton class that performs some DB operation, every activity will call this class, and i need to pass context to it.
This is what each activity will do.
AnalyticsWrapper analyticsWrapper= AnalyticsWrapper.getInstance();
analyticsWrapper.reportView(MainActivity.this)
Now i am little confused about what can go wrong when i am passing activity reference to a singleton class.
I have few questions.
What is the good way of passing context to a long running task.
Is it better if i pass getApplicaitonContex() instead of
MainActivity.this here.
Will it increase memory, when each activity will be passing its context to singleton class, and it can lead to memory leak.
I don't think there is anything wrong using application context for DB Singleton, it will likely outlive Activity so passing Activity Context will leak. I've been passing App Context to Database instances for a long time and it never caused any issue with increasing memory or functionality.
So this my inner class of a base adapter implementation. Note it is for an expandable list view but I use the same process of instantiation for all my list views
class GamesAdapter extends BaseExpandableListAdapter
{
private Context context;
public GamesAdapter(Context context)
{
this.context = context;
}
}
My question is , how do I dispose of this context because after some reading holding a context is a reference to activity so when I rotate the old instance may not be GC'ed thus a memory leak. Please help me
When the screen orientation changes the system will (by default) destroy the current activity and create a new one while giving you a chance to maintain its state. Cant you just set the context again ? im not sure if your handling the config change yourself.
me personally, I'd just pass in getApplicationContext() anytime i need a context since it does not depend on the activity lifecycle ( its not an activity context). But you can also get the context from a View in your getChildView() etc.
Further, if your list is going to be rebuilt on the config change anyway cant you just make its constructor take in the activity context you want ? that way it gets renewed ? So im not seeing where the leak would be yet.
If you rotate the screen the Activity is destroyed but also your BaseExpandableListAdapter implementation. So Android will create a new instance of the Activity and a new instance of your adapter, you don't have to worry about it.
I am developing an application where I've passed the Activity's context into a class derived from Object.
Is there anything wrong with doing this?
Maintaining an instance of a Context like that of an Activity or Service is going to open up ways for memory leaks.
However, keeping a reference to the instance returned by getApplicationContext() should be harmless.
There's nothing inherently wrong at all. Every View class does that, for instance.
The only danger is maintaining a reference to an Activity after it is destroyed. This is a common source of memory leaks. See the blog post Avoiding memory leaks for more information about this.
View subclasses avoid leaking because references to the views themselves generally go away when the activity is destroyed. If your class instance that is maintaining a reference does not go away like that, then you need to arrange for the reference to go away. One option is to override onDestroy for your activity and do some clean-up there. Another is to use a SoftReference instead of a hard reference to the context.
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 extended View and passed it an instance of my Activity so the view can access some member variables and methods.
But now I'm thinking this could be a potential memory leak, because even after the Activity is destroyed, it still has a reference to the view in a member variable, and vice versa. So the garbage collector may never clean them up.
However, I've seen in some of the Google API demos and examples cases where they have passed the Activity to the View as a listener.
This is fine, remember that any ordinary View you create programatically with its constructor takes a Context as its argument- usually the Context you give the constructor is just this, or the Activity itself. So your View already has a reference to its Activity. You can also get this inside the View class using its getContext() method.
When the Activity is destroyed, it will remain in memory until the GC can remove it. But as part of its onDestroy method, it sets the reference to any Views it contains to null, and so on down the View tree. Then the GC can safely remove all its component Views. Once that is complete, there are no references left to the Activity and another GC pass may delete it.
All the View constructors take the Context as a parameter so they already have a reference. Maybe post the code for the custom view so we can review it.