Android Admob 4.1.1 имеет утечку памяти (см. приложенный тестовый проект). Причина/исправить/обойти?

У меня есть тестовый проект, который демонстрирует утечку памяти, вызванную Admob 4.1.1.

Базовый сценарий: у меня есть два действия, и я несколько раз переключаюсь между основным и дополнительным действием. Затем я переключаюсь на DDMS и форсирую несколько GC. Затем сделайте дамп HPROF и посмотрите на гистограмму, отфильтрованную com.test*, чтобы увидеть, сколько существует основных и вспомогательных действий. Мои скриншоты гистограммы прилагаются:

Утечка! утечки

Затем я закомментировал рекламу в xml и перезапустил, и утечек не было:

Теперь утечки нет нет утечки

Я нашел несколько соответствующих сообщений об утечках Admob, например здесь: Android AdMob вызывает утечку памяти?

Вот список вещей, которые я пытался решить проблему:

  1. Подождите некоторое время, а затем запустите gc
  2. Не загружайте объявление в oncreate, а создайте поток для ожидания, а затем загрузите его.
  3. Пробовал предыдущую версию Admob (ту, что написана не Google)
  4. Вызывается adView.destroy() в методе действия onDestroy().
  5. Отвязка от этого ссылка

Очевидно, что ничего из этого не помогло.

Вот тестовый проект, который я написал:

(Обязательно задайте свой собственный идентификатор издателя при запуске тестового проекта)

загрузить проект тестовой утечки для Android

Если это имеет значение, я тестирую свой SGS2 с прошивкой Cyanogenmod.

Происходит ли это для других людей, когда они запускают этот проект?

Кто-нибудь знает причину, исправление или обходной путь?

Спасибо


person timothyjc    schedule 08.10.2011    source источник
comment
Мой лучший обходной путь — использовать развязку, о которой я упоминал в посте. Это сводит к минимуму объем просочившихся действий, так что вы можете открыть сотни из них, не получая OOM. Не совсем идеально :(   -  person timothyjc    schedule 08.10.2011
comment
См. мое решение здесь: stackoverflow.com/ вопросы/6148812/   -  person TacB0sS    schedule 03.12.2011
comment
Я не уверен, поможет ли это, но я создал ошибку на сайте поддержки Android. Admob в настоящее время принадлежит Google, поэтому они должны что-то с этим делать. Я был очень удивлен, что этого бага еще не было. ВОПРОС 59627   -  person Mark    schedule 01.09.2013


Ответы (3)


Мое приложение использует 80% разрешенных 16 МБ, и AdView просачивается при каждом изменении ориентации (поскольку тогда андроид уничтожает и воссоздает всю активность). В результате я потерял память после дюжины или около того изменений ориентации, что дало мне ужас:

10-08 10:14:47.178: ОШИБКА/dalvikvm-heap(2876): внешнее выделение 1440000 байт слишком велико для этого процесса.

10-08 10:14:47.178: ОШИБКА/dalvikvm(2876): Недостаточно памяти: размер кучи = 5191 КБ, выделено = 2877 КБ, размер растрового изображения = 18675 КБ

10-08 10:14:47.178: ОШИБКА/GraphicsJNI(2876): виртуальная машина не позволяет выделить 1440000 байт

или похожие.

Увеличение памяти можно легко увидеть в eclipse, выполнив отладку и открыв «Окно»> «Открыть перспективу»> «Другое»> DDMS, щелкнув значок «обновить кучу» и выполнив сборщик мусора «Причина». Самый простой способ проверить imho — это #Objects. Если ориентация менялась с книжной на альбомную и обратно, то количество Объектов должно быть точно таким же (и без AdView так оно и есть).

Я работаю над утечкой памяти, делая AdView статическим

private static AdView mAdView = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(mAdView == null)
    {
        mAdView = new AdView(this, AdSize.BANNER, ADMOB_PUBLISHER_ID);
    }
}

и не призывая уничтожить

@Override
public void onDestroy() {
    super.onDestroy();
    //mAdView.destroyDrawingCache();
    //mAdView.destroy();
    //mAdView = null;
}

По крайней мере, это предотвращает утечку памяти между каждым изменением ориентации.

Также я устанавливаю запрос на null после его использования. Не знаю, поможет ли это.

    AdRequest request = new AdRequest();
    mAdView.loadAd(request);
    request = null;
person Ghandi    schedule 09.10.2011
comment
Затем вы программно добавляете AdView в свой макет? Я создал LinearLayout для хранения AdView и продолжил, как вы, и утечек больше не было, но реклама также не была кликабельной, и было немного сложно отделить статический AdView от предыдущих представлений, прежде чем его можно будет использовать повторно. - person timothyjc; 09.10.2011
comment
Я внезапно начал видеть сообщения о нехватке памяти после обновления до нового Eclipse (я знаю, это не имеет значения). Я использовал библиотеку Admob с 2010 года. Я обновился до Admob 4.3.1, что потребовало от меня изменения всего моего кода Android Admob. Сейчас ошибок не вижу. - person Lucy; 01.03.2012

Мое решение

private void destroyWebView(ViewGroup viewGroup) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
    if (viewGroup.getChildAt(i) instanceof WebView) {
        WebView view = (WebView) viewGroup.getChildAt(i);
        viewGroup.removeView(view);
        view.destroy();
        return;
    }
}
}

@Override
protected void onDestroy() {
mAdView.stopLoading();
destroyWebView(mAdView);
((ViewGroup) mAdView.getParent()).removeView(mAdView);
person Bohdan    schedule 15.01.2013

Да, я строю все это динамически. Я использую removeAllViews для удаления всех представлений из моего (LinearLayout) контейнера. Затем я использую addView, чтобы вернуть их обратно. Объявление кликабельно. Возможно, в вашем случае есть какой-то прозрачный вид перед ним?

person Ghandi    schedule 18.10.2011