4

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 :-)

Ted
  • 43
  • 3
  • 1
    :Have you called System.gc(); – Mak Sep 19 '11 at 12:37
  • 1
    It will be only guesses w/o full code. Are you sure you don't persist your `AsyncTasks` with their references to the activities, or another objects which refer to the activity? For example, in your `Application` class. – ernazm Sep 19 '11 at 12:44
  • Just made the asynctask class static, and nulled all references to the activity in onPostExecute. did not fix it. – Ted Sep 19 '11 at 13:07

1 Answers1

2

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.

Community
  • 1
  • 1
Michael
  • 53,859
  • 22
  • 133
  • 139
  • I was hopeful but 'lv.setOnItemClickListener(null)' doesn't change anything. – Ted Sep 19 '11 at 13:18
  • Is it the only listener you use with the ListView? Have you tried using MAT to determine leaked roots? – Michael Sep 19 '11 at 13:38
  • Yes, I removed all of the on click listeners too. I'll try and eliminate some more code and will then try MAT. Thanks – Ted Sep 19 '11 at 13:46
  • There're some other ways how a ListView can lead to memory leaks. The only thing you need is to hold an activity reference somewhere inside the ListView, for example in the adapter or child views. Try to remove the ListView and check if this leak is still exists. – Michael Sep 19 '11 at 13:53
  • Damn, thanks a lot for the last comment. I was setting the resulting view of findViewById as a tag on a view the adapter returns (I read it as a performance tip). Leak fixed! :-) – Ted Sep 19 '11 at 14:10
  • Thank you! By the way, do you know whether the view recycler for a listview's getView() recycles across multiple activities/list views? If so, would it be beneficial to have consistent types returned by getChildType() for all of my list views? – Ted Sep 19 '11 at 14:13
  • Recycler seems to be a non-static field so it doesn't share view between activities and even between several list views in a single activity. – Michael Sep 19 '11 at 15:56