Will this dialog leak memory? - android

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.

Related

completely free memory after the Activity is closed

I need to completely free the memory which was in use by an Activity when the user closes that Activity. will using
android:noHistory="true"
be enough?
By saying
android:noHistory="true"
you tell android not to keep a reference of your activity inside the back stack of activities. That's already a good start.
The only thing that remains to be done is to be sure that you don't keep a reference yourself to your activity. For instance, don't :
store your activity's instance as a static data field. It would not be garbage collected as classes are not.
store your activity's instance as a data field of a singleton. (As transitively a singleton instance is a static data field). And so on.
If you don't keep any reference to it, and add the noHistory flag, then you can be sure it will be garbage collected.
Also, note that you can use MAT with eclipse to get sure that there is no instance of your first activity as soon as you reached the second activity.

Static Utility class with Context/Activity - Android

Over the development of an Android app I've come to a collection of utility-type methods that I have put into a static class. All these methods are used across multiple Activities and most of them do not require any information from the calling Activity.
However, I now have some methods that require the Context of the Activity and one that requires the Activity itself. Let me exemplify some of them:
getDeviceNaturalOrientation() - Uses an Activity's
getWindow().getWindowManager().getDefaultDisplay() to access the
displays rotation, width, and height to determine the device's
natural orientation.
getDeviceOrientation() - Similar to the above but to get the current
orientation
createFile() - Uses the Context to to access some resources (strings) and to
create and show some Toasts
Now, my big questions regarding this Utils class are:
So far, each function takes a Context parameter which I pass from whatever Activity I'm on, but would it be OK to create a static Context or Activity variable in the Utils class and set it at the beginning of each Activity (like in onCreate)? This variable would be used in whatever functions require a Context or Activity instance.
Assuming the above is not recommended, is it OK to pass an Activity parameter to a method or is there a reason to only pass an Activity as Context? The methods I use for the device orientation functions above are specific to Activity objects, not Context, so either I pass as Activity or pass as Context and cast into Activity (the latter sounding like a terrible idea).
Also, I am very open to the idea that this Util class may not be the way to go for these methods that require Context/Activity, so I would welcome alternatives that would still prevent having copies of these methods in each activity class that uses them.
1)A static link to a context is likely to cause a memory leak. It means that a reference to the Activity will be kept around in the static variable even after its destroyed, so all of the memory of the activity and all its views will remain valid and not be cleaned by gc. You can do this, but you have to be careful to null out the variable when done. Its better just to avoid it.
2)Its a little bit awkward to pass the activity as an Activity, but no technical reason not to. At that point we're arguing over code cleanliness/maintainability. And there are times where the non-clean solution is just easier. Of course in the cases above I'd rather pass the orientation/display/Resources objects to the function than pass the entire context or make special accessors.
I think following design should be fine when you call from Activity
MyUtility utility=new MyUtility();
utility.getDeviceNaturalOrientation(this);
utility.getFile(this);
And you can define these function like
public int getDeviceNaturalOrientation(Activity activity){
//code
return some_oreientation
}
and like this
public File getFile(Context context){
//code
//return file handler
}
Activity is the subclass of Context so you can even change the design to following
MyUtility utility=new MyUtility(this); //this refer to Activity
utility.getDeviceNaturalOrientation();
utility.getFile();
As long as you pass activity you are fine but if you do following from your activity you will get error from first method call
MyUtility utility=new MyUtility(getApplicationContext());
utility.getDeviceNaturalOrientation(); //will throw exception
utility.getFile();
And, yes first idea is not a recommended way.
I would suggest you to send a WeakReference of your Activity or getApplicationContext() (for those works which can work using it) and don't use static method because it cause memory leaks. Read Developer blog also

Is it acceptable to maintain an instance of Context in a class not derived from Activity?

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.

Android memory leak - deadly embrace

Initially I didn't pay a lot of attention to the possibility of memory leaks in Android, given the nature of managed code / garbage collection and so on. I'm thinking this might have been a bit naive. Here's the question:
Say there is an activity - MyActivity. When the OS starts it, in its onCreate() this instantiates another class (MyOtherClass) and keeps a reference to it. However say the instance of MyOtherClass also keeps a reference to the context - which happens also to be a reference to the instance of MyActivity.
Now something happens - say the screen gets rotated. OS calls the activity onDestroy() and drops the reference to that old instance of MyActivity. However, that activity instance still has a reference to an instance of MyOtherClass, which in turn has an instance to the activity.
So, am I right in thinking those two classes are going to keep each other alive for evermore?
If so, I guess possible answers are (a) don't keep a context reference, get it another way, or (b) in the activity onDestroy() drop any references it has to anything else, then it all ought to just collapse.
Java wouldn't allow cyclic links to keep each other alive (in memory). However if you have declared references static or created singleton style objects, Java won't help you there.
A good start might be reading avoiding memory leaks.

Do I really need to pass around Context instances deep into the application?

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.

Categories

Resources