android.view.ViewRoot $RunQueue $HandlerAction предотвращает сбор мусора в диалоговом окне

#android #memory-leaks #garbage-collection

#Android #утечки памяти #сбор мусора

Вопрос:

В настоящее время я создаю приложение для Android, которое будет запускаться только на планшетах. Одной из функций является отображение списка событий в (пользовательском) диалоговом окне.

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

Поскольку приложение должно запускаться в течение длительного времени, я думаю, это приведет к проблемам с памятью.

Итак, я взял дамп памяти и запустил анализатор памяти Eclipse (MAT). У меня никогда раньше не было такой проблемы, и я не слишком знаком с MAT, но вот что я предполагаю:

Я вижу, что есть несколько экземпляров моего диалогового окна и некоторый «внутренний класс» (MyDialog $ 1) все еще там. Для всех других «внутренних классов» (MyDialog $ 2, MyDialog $ 3, …) количество равно 0.

Использование «Объединить кратчайшие пути к корням GC» с опцией «со всеми ссылками» приводит меня к android.view.ViewRoot $ RunQueue $ HandlerAction, поэтому я предполагаю, что каким-то образом сохраняется ссылка на одного из моих слушателей?

Я надеюсь, вы можете сказать мне, правильно ли мое предположение (и мой способ анализа). И, надеюсь, вы можете дать мне решение или подсказку о том, как это решить.

Заранее спасибо, Свен

Комментарии:

1. Как вы создаете диалоговое окно? Когда вы регистрируете своих слушателей?

2. Диалоговое окно является подклассом android.app.Dialog. Диалоговое окно конструктора (контекст Context, тема int) переопределяется. Здесь добавляются элементы графического интерфейса и регистрируются слушатели.

3. Используете ли вы Activity.ShowDialog или DialogFragment для отображения диалогового окна?

4. Диалоговое окно отображается с помощью new MyDialog(getContext()).show();

Ответ №1:

Я думаю, что вы правы в своем предположении. Слушатель, который является анонимным классом, будет иметь ссылку на окружающий класс. Вы должны отменить регистрацию слушателей, если хотите, чтобы диалоговое окно было уничтожено.

В качестве альтернативы вы можете рассмотреть возможность использования API для управления жизненным циклом диалогового окна. Устаревший Activity.showDialog и Activity.removeDialog должен удалять все ссылки на диалоговое окно при его удалении.

В Android 3.0 и выше вы можете использовать DialogFragment вместо Dialog , и FragmentManager он должен обрабатывать его жизненный цикл за вас. См. Руководство разработчика Fragments.