I have activity A, which launches activity B via an intent. Activity A has no references to Activity B, there are also no references to Activity B in the Application singleton I am using.
When I create Activity B, several thousand objects are created. That's okay, it's an activity with a very populated ListView with lots of images.
But, when I press the back button and return to Activity A, only about a dozen of the several thousand objects are released. onDestroy() is also called for the activity. I'm using DDMS to view the heap info, and am pressing 'Cause GC' several times to force it to free memory.
I've done the same test on other apps (that use list views too) and 100% of their objects are destroyed on pressing the back button then 'Cause GC', so it's certainly not a bug.
Any advice please? :-) I've read the material in the android docs about leaking contexts, but that's not helpful since i'm not referencing the activity (or anything in it) being destroyed elsewhere. Also, I have many other activities which work the same way, and don't release all memory on destroy. I must be missing something obvious?
Edit: I just realized i'm using AsyncTasks which have references to the activity (either passed as arg into doInBackground() or accessible via outerClass.this. Could they be hanging around in the thread pool, even after onPostExecute() ?
Edit: It leaks even if I go back before running any asynctasks :-(
Edit: No leak before running asynctasks if I remove admob code, but still leaks in the activites which do use asynctasks.. so asynctask is still a good candidate :-)
I believe there's a bug in the ListView implementation. Take a look at this question: Android: AlertDialog causes a memory leak.
Here's a bug report: http://code.google.com/p/android/issues/detail?id=12334. It's declined but in my opinion it must be reopened.
Related
Right now I'm developing a game in Android (OpenGL ES 1.1) and I'm seeing that whenever I create a new SurfaceView (GLView) its thread is created. That's ok. The problem comes when I want to finish the Activity that holds the SurfaceView (and go back to the menu). It seems that the activities are not released because each GLThread is referencing it. This may finish with an OOM error.
Some MAT pictures:
The first picture: the MarkitActivity represents each single instance of the Activity that deals with SurfaceView.
The second picture: The list of all the activities in memory.
The Third Picture: What is holding the Activities from GC.
If any code is needed I will post it. Nevertheless I have already tried the following things:
->Weak reference of the Activity Context to the renderer and to the surfaceview.
->Application Context instead of Activity Context (in normal and weak mode).
->Trying to stop (in a hard way) the thread (interrupt) and waiting for join (Which the program does it, but the thread does not care, it is still there...)
->Trying without debugging, just in case in debugger mode the values changes (the MAT pictures are without debugger).
->Trying the Activity as singleInstance mode. Weird results and errors everywhere.
->onPause and onResume are correctly controlled for the view.
Any hint, idea, question or help will be really appreciated. Thanks in advance!
Carlos.
I had a similar problem with threads (but not using OpenGL), and end up solving it using a simple trick.
Before exting activity (in onPause() or onStop(), try nulling the thread like this:
myThread = null;
It seems that it makes the Thread GC collectable, and therefore you activity becomes also collectable.
It worked for me, as well as for some people with similar problems to whom I gave the same suggestion.
Regards.
My application has several components including a ListActivity and a MapActivity. I'm running into a weird problem where parts of those activities seem to be deallocated after resuming my application from background.
It's fairly deterministic. I'll return home from my application, then run other application/go on browser and then return to my application. Then my MapView disappears and other components are gone or distorted. Anyone run into something like this?
Memory is taken back by the system if it goes onPause() and the memory is needed by other Apps (Garbage collection). You need to put setContentView of your activities in your onResume() method overload if you need it to resume the old status. Check the activity life cycle
I'm getting an OutofMemoryError for my android application, and am a bit confused as to whats going on. Basically what happens is, I'm able to run it the first few times, but when I try to quit out of it and then open it again quickly and repetitively, I get an out of memory error.
I've tried researching this topic, and have found that the recycle() method has commonly been the problem. However, I've called the recycle method on each of the bitmaps (which are stored in an object container, stored in an arraylist), but was still getting the problem.
After doing this, I tried using the Eclipse Memory Analyzer to look at heap dumps, when I came across something weird. After quitting out of the activity (back into the launcher activity, and then opening up the activity again via a button, I took screenshots of the heap dump using the memory analyzer. It turns out, with each time I quit and re-entered the activity, another instance of the activity object was being created, and the old ones weren't being released, even though the onDestroy() method was being called (which also had the recycle/cleanup code.
I then tried overriding the finalize method to see if it was being called when the activity quit out back into the launcher activity, but it wasn't being called. I read on some other stackoverflow threads that finalize() isn't always called, so in the end, I'm still not sure whats going on.
Ultimately, my question is this:
How am I supposed to ensure that the Activity object (the activity object itself, not the stuff created from the activity) is released after quitting out from the activity into another activity?
Sounds like you application suffers from memory leaks, i recommend you to follow the links below:
Avoiding Memory Leaks
Memory management for Android Apps
One option is setting the launch mode to singleInstance or singleTask in your manifest file. This would make sure that another instance of the Activity is not created.
Documentation Example
One way to release your object of activity is calling it onDestoy() method..Take an object of your activity make it public static and make it null in onDestroy()
Public static Your_activity obj;
And then in onCreate method initalize obj by this
obj=this;
and in onDestroy() method do this:
obj= null;
My question is a little bit complicated.
I want to understand how the app treats resources (especially images for backgrounds, buttons, etc.) when Activity is started, then suspended.
For example, I start Activity A, it shows all the images on the screen, eats its memory, then another Activity B is started and A is suspended. What happens to all the images, resources, etc.? When they are freed? How can I take control over them? Should I not keep the Activity A in the memory and remove it from the Activity stack?
If you need any clarification for my questions, pls write me!
Thanks in advance!
Danail
Activity doesn't free resources until it's finished. But in most cases it mustn't be a problem for you. In my opinion, you shouldn't add your own resource management and make your code complicated in most cases.
But if you really think that your app can be out of memory, you should check it with something like MAT. Problems with memory may be caused by memory leaks, not heavy memory usage.
Eventually, when you're absolutely sure that you have to do something to reduce memory usage, you can do some memory optimization. For example, you can save memory-consuming objects (e.g. large images) to local storage in onStop() and load them in onStart(). I think using onPause()/onResume() for this purpose is a bad idea, because Activity is partially or even fully visible.
In theory, you can even destroy all your widgets in onStop() and restore them in onStart(), but it can make your app too slow. And, of course, in this case state saving must be implemented by you.
Finishing activities may seem to be a good idea, but I think it's not. Firstly it makes your work slower. Secondly you must manage activity stack and state of activities yourself.
For example, Activity A starts Activity B. So, Activity B must know what to do when user presses Back button. When user presses back button you should start Activity A and restore its state. But what if user terminates this app. In this case you must initialize Activity A with its default state. So, you have to implement a lot of additional logic.
In conclusion I'll repeat the main idea one more time: don't optimize memory usage if you aren't absolutely sure you have to!
Okay so we have the following situation:
A > onCreate
A > onStart
A > onResume
A > Use up a load of memory (A could even use up too much and crash)
A > Launch activity B
B > onCreate
A > onPause
B > onStart
A > onStop
B > onResume
B > Use up a load of memory
If B uses up enough memory then the Android system will kill activity A (you'll notice the onPause and onStop methods of A have already been called so it's already been given a chance to save it's state)
If you then press the back button the Android system will just start activity A again (and if it's clever it should remember it's last state) so it looks like nothing ever happened to the user.
So to be a bit clearer: if you start B and then finish A, B will essentially just replace A in the activity stack and pressing the Back button in activity B will just exit your and app and not return to activity A.
If on the other hand you start B without finishing A, then pressing the back button in B will take you back to A. While activity A is in the background it could be killed to reclaim memory, but Android will recreate it as needed when the user navigates through the activities stack.
Also if you have in memory-caches of multiple objects (e.g. bitmaps/drawables) then back your collection by SoftReferences so that the GC can clear them up if it's running low on memory.
You should design your app so that it's memory usage is low, but you can count on the framework do it's best in memory management. So, do not work too hard with removing unused stuff, only in cases when it's obvious that your app is eating too much memory.
When the available memory goes down, the framework will stop and remove activities and services which are not associated with the current task. If your app eats up even more memory, the framework will stop your activities which are in the background. Then comes the services associated with your app and the last one to finish off will be the current activity.
When the framework stops an activity it does keep record of the activity stack, the intents used for starting the activity and the bundle returned by onSaveInstanceState(), so it can recreate the last known state of the activities. Also, the framework can unload unused resources (drawables, etc.) when not in use and reload them when needed.
Well before replying to your questions, I have certain facts to discuss.
As per the life cycle of the Activity, if we call finish() then the onStop() called and finally the onDestroy() which eligibles that Activity for Garbage Collection and remove from the Activity Stack of Android.
Android is maintaining the Drawable cache for the Activity designing and displaying on the screen. So if you disable the drawable cache on the Activity onCreate().
So the best practice is to disable drawable cache on the onCreate like this:
LinearLayout v = (LinearLayout) findViewById(R.id.mainLayout);
v.setDrawingCacheEnabled(false);
and to call finish(); on the onPause();
You have very little control over memory when you writing Java code. This is a good thing for most of the cases. Actually most of the application do not need to worry about memory.
To answer your question, all the object for activity A will still be in memory when it is suspended. VM will start GC when it needs resource.
Is it a good practice to null references to Activity Context, when my Activity finishes? I have 3 AsyncTask's, each of them can be running in several instances simultaneously. The update the UI in onPostExecute(). Nulling all Activity Context references in onDestroy() would be quite difficult and make the code messy. What is the best thing to do?
Check WeakAsyncTask for an example from Google of an asynctask that doesn't keep references alive beyond the activity lifecycle, and BetterAsyncTask from DroidFu for an example of a way to wire AsyncTasks so they can reconnect to new activity instances (after a rotation, for example); usage example is here.
There's probably not too much harm in keeping the references to Activity around for a short operation (e.g. a single small web request or small file write), but if there's the possibility for the tasks to pile up, it could cause a problem. For example, if your app reads a 200KB XML file from a server on creation, which let's say can takes 1 minute or more over EDGE, a quick flip of the phone open/closed 3 or 4 times could lead to 4 retained Activity instances -- you can run out of memory pretty quickly in this situation, not to mention the duplicated work.
For any really long-running processes, though, you should definitely consider an IntentService instead of an AsyncTask. They're designed for longer-running processes that aren't really tied to a specific activity - like how you can send an MMS and leave the activity to go do other things, and you get a nice happy toast informing you of the completion of the task whenever it finishes.
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself). Try using the context-application instead of a context-activity. Nulling the references is not needed when you do not need the opposite because of the memory troubles.
If the tasks will be eligible for garbage collection themselves shortly after your Activity finishes, I see no problem in keeping the references around.
If the tasks do outlive the activity for a significant amount of time, you should set all references to the Activity Context to null. See also the article Avoiding Memory Leaks.
Either way, it is good practice to use the Application Context (getApplicationContext()) instead of the Activity Context whenever you can. In this case you can't do this, because you need to post UI messages; I'm just mentioning it for completeness.
You can hold context reference using Weak reference. http://developer.android.com/reference/java/lang/ref/WeakReference.html
Weak referenced objects can be GC'd. You should just do check if you context reference is still valid every time you use it.