Android AdView导致内存泄漏
我用的是AdView和LeakCanary。onDestroy中承载adView调用adView.destroy()的片段,但LeakCanary显示承载此片段的活动是由com.google.android.gms.common.api.a.a.i泄漏的Android AdView导致内存泄漏,android,memory-leaks,admob,adview,Android,Memory Leaks,Admob,Adview,我用的是AdView和LeakCanary。onDestroy中承载adView调用adView.destroy()的片段,但LeakCanary显示承载此片段的活动是由com.google.android.gms.common.api.a.a.i泄漏的 . 堆转储还表明存在内存泄漏。当我删除AdView.loadAd()并且不在片段中加载Ad时,就没有泄漏。有什么想法或建议吗?谢谢 您可以尝试以下方法吗: adscontainer = findViewById(R.id.RLadVi
. 堆转储还表明存在内存泄漏。当我删除AdView.loadAd()并且不在片段中加载Ad时,就没有泄漏。有什么想法或建议吗?谢谢 您可以尝试以下方法吗:
adscontainer = findViewById(R.id.RLadViewContainer);
mAdView = new AdView(MainActivity.MemoryLeakContainerActivity);//THIS IS THE TRICK ;)
mAdView.setAdSize(AdSize.BANNER);
mAdView.setAdUnitId(getResources().getString(R.string.banner_ad_unit_id));
adscontainer.addView(mAdView);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mAdView.getLayoutParams();
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mAdView.setLayoutParams(lp);
RequestConfiguration requestConfiguration = new RequestConfiguration.Builder()
.setTestDeviceIds(Constants.testDevices)
.build();
MobileAds.setRequestConfiguration(requestConfiguration);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest); //Move this line to the right place, wherever you need.
if (mAdView != null){
mAdView.setAdListener(null);
adscontainer.removeAllViews();
adscontainer = null;
mAdView.destroy();
mAdView = null;
}
- 把你的逻辑移开
- 首先从容器中删除您的
,然后调用destroy(),即adView
AdView adview = new AdView(getApplicationContext());
我的依赖项是com.google.android.gms:play-services-ads:8.3.0
解决方法是在创建AdView实例时提供应用程序上下文
AdView adview = new AdView(getApplicationContext());
我认为将App Context传递给AdView并不是一个真正的解决方案。因为问题是AdView并没有释放上下文对象。因此,如果您传递它,它将不会释放应用程序上下文 因此,下面可以作为一个解决办法,真正防止泄漏
@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中销毁Adview
- 片段生命周期有方法
,当视图被销毁时会调用该方法,所以您应该在此处销毁AdViewonDestroyView
- 在您的情况下,您正在销毁onDestroy中的AdView(onDestroyView之后的),因此它是一个漏洞。因为在片段视图被销毁后AdView仍然存在
- 活动没有
方法,视图在活动的onDestroyView
中被销毁。因此,我们在onDestroy
中清除了对象onDestroy
但是如果我们在XML中使用adView,那么这是不可能做到的 因为您需要从XML中膨胀AdView,所以删除
onDestroy
中的视图将为您完成这项工作
3.在onDestroyView
在ondestory
中设置AdViewnull
。因此,AdView对象将不再被引用。垃圾收集器将对其进行清理
我希望这些信息对您有用。:) 在我的例子中,这是由于在lambda范围内使用MobileAds初始化代码和
this
引起的。将this
更改为applicationContext
后,它被修复
之前:
MobileAds.initialize(this, "ca-app-pub-0000000000000000~0000000000")
之后:
MobileAds.initialize(applicationContext, "ca-app-pub-0000000000000000~0000000000")
我尝试了stackoverflow论坛和所有其他Google论坛讨论的所有解决方案。内存泄漏似乎不稳定:如果用户在显示广告之前离开活动,则内存泄漏的可能性更高 唯一对我有效的方法就是在一个活动中包含内存泄漏 第一项建议: 不要将adview直接添加到XML布局文件中。如果您按照官方文档()中的说明操作,肯定会导致内存泄漏。 相反,按编程方式添加adview:
<RelativeLayout
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/RLadViewContainer"
android:layout_width="match_parent"
android:layout_height="50dp"
>
<com.google.android.gms.ads.AdView <<< REMOVE IT
android:id="@+id/adView" <<< REMOVE IT
android:layout_width="wrap_content" <<< REMOVE IT
android:layout_height="wrap_content" <<< REMOVE IT
android:layout_centerHorizontal="true" <<< REMOVE IT
android:layout_alignParentBottom="true" <<< REMOVE IT
ads:adSize="BANNER" <<< REMOVE IT
ads:adUnitId="@string/banner_ad_unit_id"> <<< REMOVE IT
</com.google.android.gms.ads.AdView> <<< REMOVE IT
</RelativeLayout>
adscontainer = findViewById(R.id.RLadViewContainer);
mAdView = new AdView(MainActivity.MemoryLeakContainerActivity);//THIS IS THE TRICK ;)
mAdView.setAdSize(AdSize.BANNER);
mAdView.setAdUnitId(getResources().getString(R.string.banner_ad_unit_id));
adscontainer.addView(mAdView);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mAdView.getLayoutParams();
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mAdView.setLayoutParams(lp);
RequestConfiguration requestConfiguration = new RequestConfiguration.Builder()
.setTestDeviceIds(Constants.testDevices)
.build();
MobileAds.setRequestConfiguration(requestConfiguration);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest); //Move this line to the right place, wherever you need.
if (mAdView != null){
mAdView.setAdListener(null);
adscontainer.removeAllViews();
adscontainer = null;
mAdView.destroy();
mAdView = null;
}
注意:这是为了在底部显示横幅,并带有“中心水平”和“对齐父项底部”选项
adscontainer = findViewById(R.id.RLadViewContainer);
mAdView = new AdView(MainActivity.MemoryLeakContainerActivity);//THIS IS THE TRICK ;)
mAdView.setAdSize(AdSize.BANNER);
mAdView.setAdUnitId(getResources().getString(R.string.banner_ad_unit_id));
adscontainer.addView(mAdView);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mAdView.getLayoutParams();
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mAdView.setLayoutParams(lp);
RequestConfiguration requestConfiguration = new RequestConfiguration.Builder()
.setTestDeviceIds(Constants.testDevices)
.build();
MobileAds.setRequestConfiguration(requestConfiguration);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest); //Move this line to the right place, wherever you need.
if (mAdView != null){
mAdView.setAdListener(null);
adscontainer.removeAllViews();
adscontainer = null;
mAdView.destroy();
mAdView = null;
}
public static MainActivity MemoryLeakContainerActivity;
public MainActivity() {
super();
if (MemoryLeakContainerActivity != null) {
throw new IllegalStateException("MemoryLeakContainerActivity is already created");
}
MemoryLeakContainerActivity = this;
}
谷歌论坛正在讨论这个问题:不幸的是,仍然存在内存泄漏。看起来adView保留了对活动的引用。我从来没有在adView中遇到过任何内存泄漏,我们正在使用DFP。您能否确保您正在使用最新的播放服务。我肯定这是另外一回事,但如果没有看到一些源代码,我就不能说。你用LeakCanary或堆转储测试过应用程序吗?我使用的是最新的8.1.0播放服务,我使用的是LeakCanary。但这里有几个(潜在的)区别:1)我们使用DFP,即
com.google.android.gms.ads.doubleclick.publisherView
2)我不是在广告中使用片段,而是直接在活动视图树中添加和处理。我也有同样的问题,你解决了吗?但是如果我们使用XML格式的adView,那么这是做不到的。我试图销毁adView onDestroy,但没有任何帮助。@Funkyidol ya布局充气器很可能将该活动作为布局xml中adView的上下文提供。以编程方式向viewgroup添加视图并没有那么糟糕。这是我唯一能解决这个问题的方法。遗憾的是,我现在无法将其添加到XML布局中…我以编程方式添加AdView,并将其从片段的onStop()方法的父视图中删除,正如这里所提到的:我还使用应用程序上下文创建AdView的实例。这可能不适用于中介某些ad网络,因为某些中介适配器将