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.
Related
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()
}
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.
This is not my code. I just arrived at this site and am doing code review.
They have a class which is an extension of Dialog.
It has been defined as a singleton.
On the first call the context is passed to the getInstance method.
It instantiates the class passing the received context to the "super" within the constructor.
Then it saves it - same as in any singleton.
It then displays the dialog. After user interaction it starts a new activity and closes the dialog via "closeDialog".
However, it is still alive since the static holder for the instance is still there.
Will this then hold on to the activity that created it (and was passed on the "getInstance" call and into the "super()" when creating the instance)?
They keep the instance alive because they then use it for calls from other places and have values that need to be carried over.
I know this code stinks but I want to be sure that it does leak memory (the first activity) before I make them re-write it (or re-write it myself - which is more likely).
Yes it could. If the code starts other activities, then yes. If only the one activity is ever used, then most likely not. The reason being, dialogs must be instantiated with an activities context (it'll crash with the Application context). If that activity is set to be destroyed, garbage collection won't clean it up until all references to it are destroyed. If this singleton dialog lives outside the activity (which should be the case), then it'll continue referencing the activity and prevent GC from cleaning it up. You can read more about leaking contexts here: Avoiding memory leaks
As you stated the code is bad, and using a singleton dialog like that is just plain wrong (whether it leaks or not). There are better ways of maintaining data between states.
Instead of creating and holding Dialog inside Singleton class, build the dialog in that Singleton class but return Dialog instance to the caller class. So calling Activity will be responsible for dismissing Dialog and i believe there will not be memory leak.
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?