Утечка ListView утечки памяти в Android из-за AudioManager - PullRequest
21 голосов
/ 22 июня 2011

У меня есть ListView, и я ожидаю, что он будет очищен из памяти, когда действие закончится. Тем не менее, похоже, что это протекает. Когда я проверяю дамп памяти и получаю pathToGC для ListView, я получаю следующее:

Class Name                                                          | Shallow Heap | Retained Heap 
android.widget.ExpandableListView @ 0x4063e560                      |          768 |        39,904 
|- list, mList com.hitpost.TeamChooser @ 0x405f92e8                 |          176 |         1,648 
|  '- mOuterContext android.app.ContextImpl @ 0x40657368            |          160 |           304 
|     '- mContext android.media.AudioManager @ 0x40662600           |           40 |           168 
|        '- this$0 android.media.AudioManager$1 @ 0x406626b0 Unknown|           24 |            24 

Я вижу, что этот же контекст просачивается во многих моих ListView's. Хитрость в том, что я вообще не использую AudioManager где-либо в своем приложении, из приложения вообще нет звука. Пожалуйста, помогите, это сводит меня с ума. Очевидно, пытаясь выяснить, почему это происходит и в чем может быть основная проблема?

Ответы [ 8 ]

8 голосов
/ 24 апреля 2015

Не связано с утечкой OP, но для людей, которые пришли сюда из-за AudioManager, вызывающего утечку:

Если вы видите эту утечку, потому что вы используете VideoView, вероятно, это из-за этой ошибки: https://code.google.com/p/android/issues/detail?id=152173

VideoView никогда не выпускает AudioManager, если загружается видео.

Исправление, как упомянуто в ссылке, создает VideoView вручную с помощью ApplicationContext.

Редактировать: этот обходной путь будет работать,до ... если видео декодер говорит, что у видео есть проблема с кодированием.VideoView пытается вызвать AlertDialog, используя контекст приложения.Чем происходит сбой.

Единственное, что я могу обдумать, - это продолжать создавать вид видео с использованием контекста активности, а в Activity.onDestroy установить mContext AudioManager в контекст приложения с помощью отражения.

Примечание: необходимо получить AudioManager с использованием activity.getSystemService (Context.AUDIO_SERVICE), а не action.getApplicationContext.getSystemService (Context.AUDIO_SERVICE), поскольку AudioManager является переменной-членом Context (вы получите неверный экземпляр AudioManager, если получите его из приложенияcontext).

Наконец, вы можете задаться вопросом, почему переменная-член (AudioManager) не позволяет классу (Activity) собирать мусор.Из анализатора памяти видно, что AudioManager принадлежит собственному стеку.Поэтому AudioManager как-то не очистился сам по себе.

5 голосов
/ 18 марта 2012

В вашем коде есть несколько ссылок на AudioManager, которые вы не создаете активно.Например, у каждого кликабельного View может быть один для воспроизведения звуков onClick [ source ].Я предполагаю, что это ссылка.

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

Причиной вашей утечки может быть то, что вы держите какой-то объект View в своем коде ListView (Adapter?).Если вы держите их рядом, то у вас может быть View, который имеет AudioManager ссылку и который сохраняет Context ссылку)

4 голосов
/ 21 декабря 2012

У меня была такая же проблема, но она исчезла после следования приведенному ниже совету.

Мистер Гай рекомендует не делать дампы кучи в отладчике и вызывать несколько сборщиков мусора, прежде чем получить дамп. https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ew6lfZUH0z8

1 голос
/ 10 мая 2014

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

0 голосов
/ 27 июля 2015

Это очень простое действие, которое повторяет проблему (по крайней мере, на Android 4.0.3)

public class MainActivity extends Activity {

    int image[];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
        image = new int[1000 * 1500 * 4];
    }
}

Как вы можете видеть, нет видов или макетов, связанных с активностью, также я установил профиль "Silent" в настройках звука системы и отключил "Vibrate on touch".

Теперь, после нескольких (5-7, в зависимости от вашего heapSize) перезапусков это действие генерирует java.lang.OutOfMemoryError при попытке создать новый массив.

07-27 19:54:10.160  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 25ms
07-27 19:54:10.190  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed 23449K, 43% free 32591K/56391K, paused 30ms
07-27 19:54:10.260  22542-22543/? D/dalvikvm﹕ GC_CONCURRENT freed 0K, 1% free 56029K/56391K, paused 3ms+3ms
07-27 19:54:11.850  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 20ms
07-27 19:54:11.880  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed <1K, 1% free 56040K/56391K, paused 29ms
... Out of memory on a 24000016-byte allocation.

Сброс .hprof Я также видел 2 действия, одно из которых проводится AudioManager.

Вызов «Кучи обновлений», а затем «Сбор мусора» в Android Device Monitor действительно удаляет активность из памяти, что и указывает logcat в этой процедуре

07-27 19:44:23.150        85-85/? I/DEBUG﹕ #06  pc 000382cc  /system/lib/libdvm.so (dvmCollectGarbageInternal(GcSpec const*)+1204)

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

Это мне кажется ошибкой в ​​Android. Обходной путь должен был бы явным образом вызвать image = null в OnStop () или onFinish () действия. Это, конечно, не удобно.

0 голосов
/ 21 января 2014

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

Для этой деятельности я получал то же, что упомянуто выше в отчете hprof.

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

0 голосов
/ 15 ноября 2013

Самая распространенная причина, которую я обнаружил в своем приложении, связана с инициализацией некоторых компонентов через файл XML.Когда вы делаете это, Activity Context вводится, но иногда все, что вам нужно, это ApplicationContext.Что касается Web View в Android, эта техника мне очень помогла.

0 голосов
/ 13 марта 2012

Если ваше приложение вылетает из-за утечки памяти, вы можете избежать этого сбоя, используя try - catch (java.lang.outofmemory).Дело в том, что GC вызывается самой JVM, поэтому программист не имеет никакого контроля над этим.Вы можете установить приложение на SD-карту, в этом случае будет использоваться память SD-карты.Утечка памяти не произойдет.

Просто перейдите к файлу манифеста, там должна быть версия №.название версии, там также должно быть «Место установки», сделайте его «предпочесть внешний».

...