Android - утечка памяти или? - PullRequest
2 голосов
/ 07 апреля 2011

два дня назад я кое-что заметил. У меня есть счетчик на карте деятельности. В методе действия OnCreate () я заполняю счетчик данными. После этого я запускаю анализатор кучи в DDMS и начинаю открывать / закрывать счетчик. Я заметил, что виртуальная машина выделяет память, когда я открываю вращающиеся элементы, но когда я закрываю ее, виртуальная машина не освобождает эту память. Я попытался запустить GC, но память все еще распределена. я сделал это 20 раз один за другим, и выделенная память увеличилась с 3,5 МБ до 7 МБ. Что случилось? Я обнаружил проблему в группах Google, но они еще не ответили.
Утечка памяти спиннера

Я переписываю весь свой код в адаптере счетчика, но проблема все еще остается. Я прочитал несколько советов в этой теме

Избегать утечек памяти

Что-то, чего я не получил:

Когда Drawable присоединяется к представлению, представление устанавливается как обратный вызов для Drawable. В приведенном выше фрагменте кода это означает, что drawable имеет ссылку на TextView, который сам по себе имеет ссылку на действие (Context), которое, в свою очередь, имеет ссылки почти на что угодно (в зависимости от вашего кода.)

Что это значит? Если у меня есть текстовое представление и я установил его как объект для рисования (я заметил, что объект для рисования является статическим), у объекта с видом на текст есть ссылка на объект для рисования, а у объекта с возможностью рисования также есть ссылка на вид? Если это правда, они становятся неразрушаемыми GC, потому что у них обоих есть ссылки друг на друга? Что это за обратная ссылка (обратные вызовы) между объектами?

1 Ответ

18 голосов
/ 02 мая 2011

Извините, я не могу помочь вам с проблемой Spinner, но я могу попробовать вторую часть:

Сообщение от Romain Guy на блоге разработчика Android объясняет две важные вещи.

Во-первых:

Когда вы создаете представление (TextView, ImageView ...), вы не должны создавать его в контексте действия

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

В противном случае представление получает ссылку на вашу деятельность и никогда не будет освобождено.

Вместо этого, когда вы создаете представление программно, вы должны использовать контекст приложения:

TextView label = new TextView(getApplicationContext());

Во-вторых:

Когда вы связываете Drawable с View, он сохраняет обратный вызов вашей активности через Context. Если вы оставите его, он потеряет память, когда ваша деятельность будет уничтожена.

Чтобы избежать этого, нужно «установить нулевые обратные вызовы хранимых элементов рисования при уничтожении действия», например, с помощью ImageView:

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

Вы должны сделать то же самое для фона, который можно нарисовать ...

Надеюсь, это поможет.

...