Android AdView泄漏,可能是由于某些内部后台线程

Android AdView泄漏,可能是由于某些内部后台线程,android,android-fragments,memory-leaks,admob,Android,Android Fragments,Memory Leaks,Admob,我在由片段创建的窗口中显示AdMob广告横幅。这是可行的,但我遇到了奇怪的泄漏问题,我还不明白。当我多次打开和关闭应用程序时,每次都会正确销毁广告片段,但控制该片段的MainActivity正在泄漏: 有罪的是这一行代码: adRequest = new AdRequest.Builder().addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build(); mAdView.loadAd(adRequest); (您可

我在由片段创建的窗口中显示AdMob广告横幅。这是可行的,但我遇到了奇怪的泄漏问题,我还不明白。当我多次打开和关闭应用程序时,每次都会正确销毁广告片段,但控制该片段的MainActivity正在泄漏:

有罪的是这一行代码:

adRequest = new AdRequest.Builder().addTestDevice(DEVICE_ID_MOTO_G).addTestDevice(DEVICE_ID_ZTE).build();
mAdView.loadAd(adRequest);
(您可以在下面看到,我已经尝试取消adRequest,但没有结果。)无论如何,当我评论这两行时,泄漏不会发生。我对它进行了两次测试,因为很难相信这个调用会泄漏,但确实如此。这是片段代码。如您所见,我甚至在
ondestory()
中取消了所有可能的内容。我可以保证调用了
onDestroy()
<代码>加载AD启动任何后台线程。我想这和那个问题有关

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();
    }
}

我幸运地找到了解决办法。在片段被销毁之前,您必须手动将AdView踢出周围的布局。在我启动并关闭应用程序大约20次后,再也没有泄漏。以下是更新的片段:

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;
        }
    }
}

可能与泄漏无关,但是
片段的
承包商必须没有参数,框架在片段恢复时不会调用承包商,您可以使用
getActivitiy()
mAddView.getContext()
获取上下文,但这没用,你是怎么泄露的?屏幕旋转?我也有同样的问题,但不幸的是,即使经过此修复,我的问题仍然存在。@eliasbagley那么您在某个地方有一个对该片段的引用,或者根本没有销毁该片段?该片段的onDestroy()方法被调用。我以编程方式添加AdView,并将其从onStop()的父视图中删除方法:我使用应用程序上下文创建AdViewwhy do you do
adView=null的实例
onDestroy
中?真没用!