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

时间:2015-02-25 19:03:44

标签: android android-fragments memory-leaks admob

我在片段创建的窗口中显示AdMob广告横幅。这很有效,但我发现了一些奇怪的泄漏问题,我还不明白。当我多次打开和关闭应用程序时,广告片段每次都被正确销毁,但控制此片段的MainActivity正在泄漏:

Leak

有罪的是代码中的这一行:

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

(你可以在下面看到我已经尝试取消adRequest,但没有结果。)无论如何,当我评论这两行时,不会发生泄漏。我测试了两次,因为很难相信这个调用会泄漏,但确实如此。这是片段代码。如您所见,我甚至取消onDestroy()中可能存在的所有内容。我可以保证调用onDestroy()loadAd启动任何后台线程。我想这与这个问题有关。

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

1 个答案:

答案 0 :(得分:3)

幸运的是,我找到了解决方案。在片段被破坏之前,您必须手动将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;
        }
    }
}