AdView вызывает утечку памяти

Я использую AdView и LeakCanary. Фрагмент, в котором размещается adView, вызывает adView.destroy() в onDestroy, но LeakCanary показывает, что Activity, в котором размещен этот фрагмент, просачивается com.google.android.gms.common.api.a.a.a.i , Сброс кучи также показывает, что есть утечка памяти. Когда я удаляю AdView.loadAd() и не загружаю Ad в фрагмент - утечки нет. Любые мысли или предложения? Благодарю.

Ответ 1

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

Моя зависимость com.google.android.gms:play-services-ads:8.3.0

A обходной путь заключается в предоставлении контекста приложения при создании экземпляра AdView.

AdView adview = new AdView(getApplicationContext());

Ответ 2

Можете ли вы попробовать следующее:

  • переместите свою логику в onDestroyView()
  • сначала удалите ваш adView из своего контейнера, а затем вызовите destroy(), т.е.

    ViewParent parent = adView.getParent();
    if (parent != null && parent instanceof ViewGroup) {
      ((ViewGroup) parent).removeView(adView);
    }
    
    adView.destroy();
    adView = null;
    

Ответ 3

Я думаю, что передача контекста приложения в AdView не является решением на самом деле. Потому что проблема в том, что AdView не освобождает объект Context. Так что это не освободит контекст приложения, если вы передадите его.

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

@Override
protected void onDestroyView() {
    super.onDestroy();
    if (adview != null && adview.getParent() != null) // inflated by XML and remove here from parent
        ((ViewGroup) adview.getParent()).removeView(adview);
    adview.destroy(); 
    adview = null;
}

1. Уничтожить рекламу в onDestroyView

  • У жизненного цикла фрагмента есть метод onDestroyView, который вызывается при уничтожении представления, поэтому в этом месте вы должны точно уничтожить AdView.
  • В вашем случае вы уничтожаете AdView в onDestroy (после onDestroyView), так что это утечка. Потому что AdView все еще там после того, как Fragment View уничтожен.
  • Деятельность не имеет метода onDestroyView, представление уничтожается в onDestroy в деятельности. Так что мы onDestroy объекты в onDestroy.

2. Удалите AdView из View программным способом.

Но если мы используем adView в XML, то это невозможно.

Поскольку вы хотите раздувать AdView из XML, удаление "View in onDestroy сделает эту работу за вас.

3. Сделайте AdView пустым в onDestroyView

Сделайте AdView null в onDestroy. Таким образом, объект AdView больше не будет ссылаться. и он будет очищен сборщиком мусора.

Я надеюсь, что эта информация полезна для вас. :)

Ответ 4

В моем случае, это было вызвано использованием MobileAds коды инициализации с this в рамках лямбды. После изменения this к applicationContext, она была установлена.

До:

MobileAds.initialize(this, "ca-app-pub-0000000000000000~0000000000")

После:

MobileAds.initialize(applicationContext, "ca-app-pub-0000000000000000~0000000000")