Android - memory leak or?

2019-04-14 05:10发布

问题:

two days ago i noticed something. I have a spinner over a map activity. In the OnCreate() method of the activity i populate the spinner with data. After that i start the heap analyzer in DDMS i begin to open/close the spinner. I noticed the VM allocate memory when i open the spinner items, but when i close it, the VM do no free this memory. I've tried to start the GC, but the memory is still allocated. i did this 20 times one by one and the allocated memory increased from 3.5MB to 7MB. What is wrong? I found an issue in google groups, but they haven't answered yet.
Spinner memory leak

I rewrite all my code in the spinner adapter, but the issue still remains. I read some advices in this topic

Avoid memory leaks

There is something i did not get:

When a Drawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)

What does it mean? If i have a textview and set it a drawable object (i noticed the drawable is static), the textview object has a reference to the drawable object and the drawable object has a reference to the view too? If this is true, they become undestroyable by the GC because they both have references to each other? What is this back-reference (callbacks) dependencе between the objects?

回答1:

Sorry I can't help you on your Spinner problem but I can have a try on the second part:

Romain Guy post on android developer blog explain two important things.

First:

When you create a View (TextView, ImageView...) you must not create it with the activity Context

// DO NOT DO THIS
TextView label = new TextView(this);

Otherwise the View get a reference to your activity and will never be deallocated.

Instead, when you create a View programatically, you have to use the application context:

TextView label = new TextView(getApplicationContext());

Second:

When you link a Drawable to an View, it keeps a callback on your activity via the Context. If you leave it, it will leak memory when your activity is destroy.

The thing to do to avoid that is to "set stored drawables' callbacks to null when the activity is destroyed" so for example whith an ImageView:

protected void onDestroy() {
    imageView.getDrawable().setCallback(null);
    super.onDestroy();
}

You have to do the same for the background drawable...

Hope it helps.