Мое рекламное объявление вызывает утечку памяти? - PullRequest
5 голосов
/ 23 февраля 2020

Я также пытался использовать ApplicationContext, но по какой-то причине он все еще протекает.

Нашел похожий пост о проблеме здесь Утечка AdActivity в AdMob (SDK 7.0) для Android, но без ответа.

Также попытался установить adlistener и объявление обнулено в onDestroy (), но безуспешно и все еще пропускает активность.

Мой код вызвал onCreate ()

private void refreshInterstitial(){
        mInterstitialAd = new InterstitialAd(this);
        mInterstitialAd.setAdUnitId("ca-app-pub-4427787827947251/4816847605");
        mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).addTestDevice("877BCC97E130A0DC62B2E5770D854496").build());

        mInterstitialAd.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {
                mInterstitialAd.show();
            }
            @Override
            public void onAdClosed() {
            }
        });
}

Leakcanary След утечки

 ┬───
    │ GC Root: Global variable in native code
    │
    ├─ mx instance
    │    Leaking: UNKNOWN
    │    ↓ mx.a
    │         ~
    ├─ com.google.android.gms.ads.internal.webview.w instance
    │    Leaking: UNKNOWN
    │    mContext instance of com.google.android.gms.ads.internal.webview.ay, not wrapping activity
    │    View#mParent is null
    │    View#mAttachInfo is null (view detached)
    │    View.mWindowAttachCount = 1
    │    ↓ w.a
    │        ~
    ├─ com.google.android.gms.ads.internal.webview.aa instance
    │    Leaking: YES (View detached and has parent)
    │    mContext instance of com.google.android.gms.ads.internal.webview.ay, not wrapping activity
    │    View#mParent is set
    │    View#mAttachInfo is null (view detached)
    │    View.mWindowAttachCount = 1
    │    ↓ aa.mListenerInfo
    ├─ android.view.View$ListenerInfo instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ View$ListenerInfo.mOnClickListener
    ├─ com.google.android.gms.ads.nonagon.ad.webview.f instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ f.a
    ├─ com.google.android.gms.ads.nonagon.ad.webview.l instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ l.e
    ├─ com.google.android.gms.ads.nonagon.ad.event.bs instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ bs.a
    ├─ java.util.HashMap instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ HashMap.table
    ├─ java.util.HashMap$Node[] array
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ HashMap$Node[].[1]
    ├─ java.util.HashMap$Node instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ HashMap$Node.key
    ├─ com.google.android.gms.ads.nonagon.shim.k instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ k.a
    ├─ com.google.android.gms.ads.internal.client.ae instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ ae.a
    ├─ com.google.android.gms.internal.ads.zzuc instance
    │    Leaking: YES (aa↑ is leaking)
    │    ↓ zzuc.zzcbw
    ├─ com.test.Activity$1 instance
    │    Leaking: YES (aa↑ is leaking)
    │    Anonymous subclass of com.google.android.gms.ads.AdListener
    │    ↓ EqualizerActivity$1.this$0
    ╰→ com.test.Activity instance
    ​     Leaking: YES (ObjectWatcher was watching this because Activity received Activity#onDestroy() callback and Activity#mDestroyed is true)
    ​     key = 40a1eb8e-c9e6-4062-b5f7-053e642e812f
    ​     watchDurationMillis = 5288
    ​     retainedDurationMillis = 258

1 Ответ

2 голосов
/ 27 февраля 2020

В соответствии с InterstitialAd Docs :

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

После повторного просмотра вашего кода я заметил, что вы воссоздаете mInterstitialAd каждый раз, когда вызывается метод refreshInterstitial(). Но согласно приведенным выше документам, вы должны создавать mInterstitialAd только один раз за onCreate().

В вашем случае основная причина утечки памяти: у вас все еще есть активный слушатель (что связано с продолжительностью жизни действия), но вы восстанавливаете новый экземпляр InterstitialAd с другим слушателем.

Итак, решение состоит в том, чтобы повторно использовать экземпляр InterstitialAd и его слушатель без повторного назначения. Я предлагаю упростить ваш refreshInterstitial() метод до этого:

private void refreshInterstitial() {
    mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).addTestDevice("877BCC97E130A0DC62B2E5770D854496").build());
}

Затем поместите mInterstitialAd назначение в onCreate(). Это решение похоже на то, которое вы можете найти здесь .

...