私もApplicationContext
を使用してみましたが、何らかの理由で依然としてリークします。
この問題に関する同様の投稿がこちらにあります Android向けAdMob(SDK 7.0)でのAdActivityリーク ですが、答えはありません。
また、onDestroy()でadlistenerとadをnullに設定しようとしましたが、運が悪く、それでもアクティビティがリークします。
私のコードはonCreate()で呼び出されます
private void refreshInterstitial(){
mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId("AD_ID");
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 Leak Trace
┬───
│ 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
InterstitialAd Docs によると:
単一のInterstitialAdオブジェクトを使用して、アクティビティの有効期間中に複数のインタースティシャル広告をリクエストおよび表示できるため、一度作成するだけで済みます。
コードをもう一度調べたところ、refreshInterstitial()
メソッドが呼び出されるたびにmInterstitialAd
を再構築していることがわかりました。しかし、上記のドキュメントによれば、onCreate()
の間に一度だけmInterstitialAd
を構築する必要があります。
あなたの場合、メモリリークの主な原因:まだアクティブなリスナーがあり(これはアクティビティの寿命にバインドされています)、新しいものを再構築します別のリスナーを持つInterstitialAd
インスタンス。
したがって、解決策は、再割り当てせずにInterstitialAd
インスタンスとそのリスナーを再利用することです。 refreshInterstitial()
メソッドをこれに簡略化することをお勧めします:
_private void refreshInterstitial() {
mInterstitialAd.loadAd(new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).addTestDevice("877BCC97E130A0DC62B2E5770D854496").build());
}
_
次に、mInterstitialAd
割り当てをonCreate()
に配置します。この解決策は、あなたが見つけることができるものと似ています here 。