Clueless О (возможно) утечке памяти Android

Я столкнулся с некоторыми раздражающими OutOfMemoryErrors , даже после того, как убедитесь, что все мои растровые изображения правильно масштабированы и т. Д. На самом деле проблема, похоже, не связана с растровыми изображениями, но я могу ошибаться.

Для тестирования и устранения ошибок я переключался между двумя действиями (назовем их «Main» и «List»), используя мой навигационный ящик (не используя кнопку «Назад»). В DDMS я вижу, что выделенная память увеличивается каждый раз, когда я возвращаюсь.

Я сделал дампы памяти и использовал Eclipse MAT для анализа 3 разных момента времени:

Screen1

Screen2

SCREEN3

Я подозреваю утечку памяти, но я не могу понять ее причину. Согласно дампам памяти, похоже, что это «Remainder» и java.lang.FinalizerReference которые продолжают расти. У пользователя в этом вопросе также есть много FinalizerReferences в его дампе памяти, но ответ не совсем ясен.

Отчет о подозрительных подозрениях, который я сделал в последний момент времени, не очень полезен, поскольку он подозревает android.content.res.Resources и android.graphics.Bitmap которые, кажется, не растут с течением времени:

Screen3LeakReport

В одном из сообщений (к сожалению, здесь нет) я видел 13 экземпляров android.widget.ListView указал как потенциальный подозреваемый в утечке.

Это увеличение памяти происходит с любым переходом между действиями (а не только основным и списком, которые я использовал в этом примере).

Как я могу найти (неочевидную?) Утечку памяти? Я долго царапал себе голову, поэтому любая помощь и советы были бы замечательными.

РЕДАКТИРОВАТЬ:

  • Bitmap (@ OrhanC1): Я прокомментировал любые экземпляры Bitmap в двух упомянутых выше действиях и память все еще увеличивается. Дамп памяти по-прежнему показывает некоторые растровые изображения, но я считаю, что они связаны с ресурсами, а не с фактическими растровыми изображениями, выделенными мной.

  • Что касается пользовательских шрифтов (@erakitin): я их использую, но я сохраняю один экземпляр каждого Typeface в моем контексте Application ( public class MyApp extends Application ) с использованием одноэлементного. Я пробовал комментировать любые ссылки на шрифты в двух упомянутых выше действиях, и память все еще увеличивается.

  • Я не думаю, что я утечка Context (@DigCamara): у меня нет каких-либо статических ссылок внутри этих двух Деяний, я использую контекст Application вместо Activity , кроме как в адаптере. Если я остаюсь в одной и той же Activity и выполняю некоторые вращения экрана, память не увеличивается.

  • Основываясь на комментарии @ NickT: я вижу, что у меня много примеров обоих действий. Могла ли эта память увеличиваться только в результате увеличения количества действий заднего стека, а не утечки памяти (я, хотя ОС справился с этим, по- видимому, не )? Если я использую FLAG_ACTIVITY_REORDER_TO_FRONT намерения FLAG_ACTIVITY_REORDER_TO_FRONT тогда память увеличивается только до тех пор, пока не будут созданы все разные действия (один раз). Полезно для этого: Android не убивает действия из стека, когда память низкая .

Похоже, причина, по которой Remainder растет, – это рост числа экземпляров Activity в заднем стеке (например, 13 экземпляров « Activity списка» + 13 экземпляров «Основной» Activity ).

Я изменил свой навигационный ящик так, что, когда пользователь нажимает кнопку «Главная» (что приводит его в «Панель инструментов» приложения), я устанавливаю Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK : Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK повторно используется, а задний стек очищается ( как рекомендовано в руководстве Android ). Фактически, я должен был сделать это уже, так как я не хочу создавать несколько экземпляров деятельности Dashboard («Главная»).

Делая это, я вижу, что действия уничтожены и выделен размер кучи (включая « Remaining » срез):

Устранение проблемы с увеличением объема памяти.

Исправляя это, я также заметил, что один из моих «Деяний» и «Растровое изображение», которые он использовал, не уничтожались, даже если задний стек был очищен (утечка). После анализа с помощью MAT я пришел к выводу, что источником этой подзадачи была ссылка на ImageView которую я сохранил в Activity . Добавив этот код к onStop() , мне удалось уничтожить как активность, так и Bitmap :

 @Override protected void onStop() { super.onStop(); ImageView myImage = (ImageView) findViewById(R.id.myImage ); if(myImage .getDrawable() != null) myImage.getDrawable().setCallback(null); RoundedImageView roundImage = (RoundedImageView) findViewById(R.id.roundImage); // a custom View if(roundImage.getDrawable() != null) roundImage.getDrawable().setCallback(null); } 

Затем я обобщил всю свою Activity и unbindDrawables(View view) FragmentActivity чтобы они вызывали unbindDrawables(View view) в onDestroy() :

 private void unbindDrawables(View view) { if (view.getBackground() != null) { view.getBackground().setCallback(null); } if (view instanceof ViewGroup && !(view instanceof AdapterView)) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } ((ViewGroup) view).removeAllViews(); } } 

Спасибо @NickT за то, что указали мне в правильном направлении.

Intereting Posts
Android: Что такое текстовый текст по умолчанию для EditText? Содержимое подталкивается под панелью инструментов при использовании animateLayoutChanges = "true" Smack RosterListener не работает в Android Преобразование прошедшего реального времени в Date Шаблон пользовательского интерфейса Android Quick Action URL-адрес фильтра андроидов в «прицельном фильтре» Ручной фокус настройки Android, касаясь Вы должны сначала вызвать removeView () родителя ребенка с помощью AlertView Как получить контрольную точку в собственном коде NDK и отладить собственный код в Android Studio? Правое выравнивание TextView с использованием силы тяжести в RelativeLayout Что произойдет, если startActivity () вызывается в уже созданную активность? Проблема: перетаскивание большого файла в эмулятор / SD-карту с помощью Eclipse DDMS Android-библиотека собирается с Gradle, но «пакет R не существует» при создании ошибки Android Studio, Gradle, OpenCV и NDK Eclipse создает расширение ActionBarActivity вместо активности