Android的AdView的泄漏,可能是由于一些内部后台线程 [英] Android AdView leaking, probably due to some internal background thread

查看:1089
本文介绍了Android的AdView的泄漏,可能是由于一些内部后台线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我显示由片段创建的窗口内的AdMob广告横幅。这工作,但我发现了奇怪的问题,漏水我还不知道。当我打开和关闭应用了很多次,广告片段被正确摧毁每一次,但控制该片段在MainActivity泄漏:

有罪的是这条线在code:

  AdRequest中=新AdRequest.Builder()addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
mAdView.loadAd(AdRequest中);

(你可以看到下面,我已经尝试过以抵消了AdRequest中,但没有结果。)无论如何,当我评论这两条线,不发生泄漏。我测试了两次,因为这是很难相信,这个调用泄漏,但它确实。这里是片段code。正如你所看到的,我甚至抵消一切都是可能的的onDestroy()。我可以保证,的onDestroy()被调用。 loadAd starty任何后台线程。我想,有这个问题做的。

 公共类SnippetFragment扩展片段
{
    私人的AdView mAdView;
    私人OnAdFinishedLoadingListener onAdFinishedLoadingListener;
    私人上下文的背景下;
    私人AdRequest中AdRequest中;    私人最终字符串DEVICE_ID_ZTE =1CA20334345BB1479C43692AFA576456487A48;
    私人最终字符串DEVICE_ID_MOTO_G =131465469A7BE1154354306540​​4B168908CB13C8D1;    公共SnippetFragment(上下文的背景下)
    {
        this.context =背景;
    }    @覆盖
    公共无效onActivityCreated(包捆)
    {
        super.onActivityCreated(包);        mAdView =(的AdView)getView()findViewById(R.id.adView)。
        mAdView.setAdListener(新AdListener的()
        {
            @覆盖
            公共无效onAdLoaded()
            {
                super.onAdLoaded();                如果(上下文!= NULL)
                {
                    onAdFinishedLoadingListener =(OnAdFinishedLoadingListener)范围内;
                    onAdFinishedLoadingListener.onAdLoaded();
                }
            }
        });        //这个莫名其妙地漏了!
        。在AdRequest =新AdRequest.Builder()addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
        mAdView.loadAd(AdRequest中);    }    @覆盖
    公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState)
    {
        返回inflater.inflate(R.layout.fragment_snippet,集装箱,FALSE);
    }    / **离开活动*时调用/
    @覆盖
    公共无效的onPause()
    {
        如果(mAdView!= NULL)
        {
            mAdView.pause();
        }
        super.onPause();
    }    返回活动时调用/ ** * /
    @覆盖
    公共无效onResume()
    {
        super.onResume();
        如果(mAdView!= NULL)
        {
            mAdView.resume();
        }
    }    / **叫activity被销毁之前* /
    @覆盖
    公共无效的onDestroy()
    {
        在AdRequest = NULL;        如果(mAdView!= NULL)
        {
            mAdView.setAdListener(NULL);
            mAdView.destroy();
            mAdView = NULL;
        }        上下文= NULL;        super.onDestroy();
    }
}


解决方案

我幸运地找到了解决办法。您必须手动踢出来的AdView周围布局,片段被销毁。无泄漏后,再我发起和关闭应用程序的20倍左右。这里是更新片段

 公共类SnippetFragment扩展片段
{
    私人的AdView AdView的;
    私人OnAdFinishedLoadingListener onAdFinishedLoadingListener;
    私人上下文的背景下;
    私人经纬度routeDestination;
    私人AdRequest中AdRequest中;
    私人的LinearLayout snippetContent;    私人最终字符串DEVICE_ID_ZTE =2353496z35752t3524267854;
    私人最终字符串DEVICE_ID_MOTO_G =4568735862378523675427897;    @覆盖
    公共无效onActivityCreated(包捆)
    {
        super.onActivityCreated(包);        snippetContent =(的LinearLayout)getView()findViewById(R.id.snippet_content)。
        AD浏览=(的AdView)getView()findViewById(R.id.adView)。
        的AdView.setAdListener(新AdListener的()
        {
            @覆盖
            公共无效onAdLoaded()
            {
                super.onAdLoaded();                如果(上下文!= NULL)
                {
                    onAdFinishedLoadingListener =(OnAdFinishedLoadingListener)getActivity();
                    onAdFinishedLoadingListener.onAdLoaded();
                }
            }
        });        。在AdRequest =新AdRequest.Builder()addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
        adView.loadAd(AdRequest中);
    }    @覆盖
    公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState)
    {
        返回inflater.inflate(R.layout.fragment_snippet,集装箱,FALSE);
    }    @覆盖
    公共无效的onPause()
    {
        如果(AD浏览!= NULL)
        {
            adView.pause();
        }        super.onPause();
    }    @覆盖
    公共无效onResume()
    {
        super.onResume();        如果(AD浏览!= NULL)
        {
            adView.resume();
        }    }    @覆盖
    公共无效的onDestroy()
    {
        destroyAdView();        super.onDestroy();
    }    私人无效destroyAdView()
    {
        如果(AD浏览!= NULL)
        {
            在AdRequest = NULL;
            adView.removeAllViews();
            的AdView.setAdListener(NULL);
            adView.destroy();
            snippetContent.removeView(AD浏览);            AD浏览= NULL;
            snippetContent = NULL;
        }
    }
}

I display an AdMob ad banner within a window created by a fragment. This works, but I'm getting strange leaking problems I don't understand yet. When I open and close the app a lot of times, the ad fragment is properly destroyed every time, but the MainActivity which controls this fragment is leaking:

The guilty one is this line in code:

adRequest = new AdRequest.Builder().addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
mAdView.loadAd(adRequest);

(You can see below that I already tried to nullify the adRequest, but no result.) Anyway, when I comment these two lines, the leaks don't occur. I tested it twice, because it was hard to believe that this invocation leaks, but it does. Here is the fragment code. As you can see, I even nullify everything that is possible in onDestroy(). I can assure that onDestroy() is called. loadAd starty any background thread. I guess that has to do with that problem.

public class SnippetFragment extends Fragment
{
    private AdView mAdView;
    private OnAdFinishedLoadingListener onAdFinishedLoadingListener;
    private Context context;
    private AdRequest adRequest;

    private final String DEVICE_ID_ZTE = "1CA20334345BB1479C43692AFA576456487A48";
    private final String DEVICE_ID_MOTO_G = "131465469A7BE11543543065404B168908CB13C8D1";

    public SnippetFragment(Context context)
    {
        this.context = context;
    }

    @Override
    public void onActivityCreated(Bundle bundle)
    {
        super.onActivityCreated(bundle);

        mAdView = (AdView)getView().findViewById(R.id.adView);
        mAdView.setAdListener(new AdListener()
        {
            @Override
            public void onAdLoaded()
            {
                super.onAdLoaded();

                if (context != null)
                {
                    onAdFinishedLoadingListener = (OnAdFinishedLoadingListener)context;
                    onAdFinishedLoadingListener.onAdLoaded();
                }
            }
        });

        //THIS SOMEHOW LEAKS!
        adRequest = new AdRequest.Builder().addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
        mAdView.loadAd(adRequest);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.fragment_snippet, container, false);
    }

    /** Called when leaving the activity */
    @Override
    public void onPause()
    {
        if (mAdView != null)
        {
            mAdView.pause();
        }
        super.onPause();
    }

    /** Called when returning to the activity */
    @Override
    public void onResume()
    {
        super.onResume();
        if (mAdView != null)
        {
            mAdView.resume();
        }
    }

    /** Called before the activity is destroyed */
    @Override
    public void onDestroy()
    {
        adRequest = null;

        if (mAdView != null)
        {
            mAdView.setAdListener(null);
            mAdView.destroy();
            mAdView = null;
        }

        context = null;

        super.onDestroy();
    }
}

解决方案

I fortunately found the solution. You have to manually kick the AdView out of the surrounding layout, before the fragment gets destroyed. No leak anymore after I launched and closed the app about 20 times. Here is the updated fragment:

public class SnippetFragment extends Fragment
{
    private AdView adView;
    private OnAdFinishedLoadingListener onAdFinishedLoadingListener;
    private Context context;
    private LatLng routeDestination;
    private AdRequest adRequest;
    private LinearLayout snippetContent;

    private final String DEVICE_ID_ZTE = "2353496z35752t3524267854";
    private final String DEVICE_ID_MOTO_G = "4568735862378523675427897";

    @Override
    public void onActivityCreated(Bundle bundle)
    {
        super.onActivityCreated(bundle);

        snippetContent = (LinearLayout)getView().findViewById(R.id.snippet_content);
        adView = (AdView)getView().findViewById(R.id.adView);
        adView.setAdListener(new AdListener()
        {
            @Override
            public void onAdLoaded()
            {
                super.onAdLoaded();

                if (context != null)
                {
                    onAdFinishedLoadingListener = (OnAdFinishedLoadingListener)getActivity();
                    onAdFinishedLoadingListener.onAdLoaded();
                }
            }
        });

        adRequest = new AdRequest.Builder().addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
        adView.loadAd(adRequest);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.fragment_snippet, container, false);
    }

    @Override
    public void onPause()
    {
        if (adView != null)
        {
            adView.pause();
        }

        super.onPause();
    }

    @Override
    public void onResume()
    {
        super.onResume();

        if (adView != null)
        {
            adView.resume();
        }

    }

    @Override
    public void onDestroy()
    {
        destroyAdView();

        super.onDestroy();
    }

    private void destroyAdView()
    {
        if (adView != null)
        {
            adRequest = null;
            adView.removeAllViews();
            adView.setAdListener(null);
            adView.destroy();
            snippetContent.removeView(adView);

            adView = null;
            snippetContent = null;
        }
    }
}

这篇关于Android的AdView的泄漏,可能是由于一些内部后台线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆