正确的onDestroy()/如何避免内存泄漏 [英] Proper onDestroy() / How to avoid memory leaks

查看:1019
本文介绍了正确的onDestroy()/如何避免内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了一些关于如何避免在Android的内存泄漏的文章,但我仍然不是很确定,如果我是正确的。

I read a number of articles on how to avoid memory-leaks in Android, but i'm still not quite sure if I got it right.

  1. 在我的应用程序由一个单一的活动
  2. 在我没有在该活动的任何私人或静态成员,所有code是从内部<​​code>的onCreate开始()。
  3. 在有一些自成一体的静态类的静态实例有时抱提述上下文查看秒。在我的的onDestroy()的方法,我把所有这些情况下为null。
  4. 在我回收所有我的位图取值。
  1. My Application consists of a single Activity.
  2. I don't have any private or static members in that Activity, all code is started from within onCreate().
  3. In have some self-contained static classes whose static instances sometimes hold references to a Context or Views. In my onDestroy() method, I set all of these instances to null.
  4. I recycle all of my Bitmaps.

Q1 :是否已足够?

什么混淆我是一个典型的例子不走,你可以在网上找到(<一href="http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/">http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/):

What confuses me is the classic example of a no-go you can find on the net (http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/):

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);

  TextView label = new TextView(this);
  label.setText("Leaks are bad");

  setContentView(label);
}

我认为,只要的onCreate 结束,标签超出范围,是GCed。

I thought that, as soon as onCreate finishes, label goes out of scope and is GCed.

Q2 :?这怎么可能创建一个内存泄漏

Q2: How can this create a memory-leak?

我的活动基本上是这样的:

My Activity basically looks like this:

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /* Statics */
    AssetUtils.initIndex(this);
    BitmapLoader.startInstance(this);

    /* frame */
    ViewGroup frame = (ViewGroup) getLayoutInflater().inflate(R.layout.frame, null);
    this.setContentView(frame);

    /* create controller */
    Controller controller = new Controller(frame, getLayoutInflater());

    /* START */
    controller.start();
}

@Override
public void onDestroy() {
    super.onStop();

    /* Statics */
    AssetUtils.destroyInstance();
    BitmapLoader.destroyInstance();
}

控制器我偶尔检索上下文使用查看#的getContext()来将它传递给手动创建查看 S等。这是从来没有静态存储的地方,只在类,它们都回去控制器成员变量。

Inside Controller I occasionally retrieve a Context using View#getContext() to pass it to manually created Views and the like. It's never stored statically somewhere, only in member-variables of classes which all go back to Controller.

Q3 :有什么是我忽略了

推荐答案

Q1。你已经采取了这种断章取义(不是开玩笑意:)

Q1. You've taken this out of context (no joke intended :)

如果你看到原来的文章,泄漏居然发生在code其中位图字段被引入下一个片段。罗马则清楚地解释了为什么它泄漏。你已经证明了code不会泄露。

If you see the original article, the leak actually occurs in the next fragment of code where the Bitmap field is introduced. Roman then clearly explains why it leaks. The code you have shown will NOT leak.

<一个href="http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/">http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/

Q2。使用活动方面,只有在没有其他选择,绝不允许对它的引用的东西与范围大于它所引用的活动范围。还有你的code不漏,据我可以看到因为没有与一个范围大于你的Activity上下文的参考。你是否怀疑它呢?

Q2. Use Activity context only where there is no other choice and NEVER allow a reference to it in something with a scope greater than the scope of the Activity it references. The code you've shown doesn't leak as far as I can see since nothing has a context reference with a scope greater than your Activity. Do you suspect that it does?

Q3。当使用位图,静态引用或不是,我在解除绑定Bitamps从视图中的onPause(习惯)(记住的onDestroy()不能保证,但它是一种,如果你被破坏无关,你的进程被杀死所以GC不是问题)。链接的文章还介绍了如何做到这一点。我已为我的任何活动处理位图的模板图案。

Q3. When using Bitmaps, static references or not, I am in the habit of unbinding Bitamps from Views in onPause() (remember onDestroy() is not guaranteed but it's kind of irrelevant as if you're being destroyed, your process is killed so GC isn't a concern). The linked article also explains how to do this. I have made it a template pattern for any of my Activities handling Bitmaps.

对不起,我只是检查。本文不说明如何解除绑定。下面是我用的模式:

Sorry, I just checked. The article does not show how to unbind. Here's the pattern I use:

@Override
protected void onPause()
{
        super.onPause();

        unbindDrawables(findViewById(R.id.mainLayout));
        System.gc();
}


@Override
protected void onDestroy()
{
        super.onDestroy();

        unbindDrawables(findViewById(R.id.mainLayout));
        System.gc();
}

private void unbindDrawables(View view)
{
        if (view.getBackground() != null)
        {
                view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView))
        {
                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
                {
                        unbindDrawables(((ViewGroup) view).getChildAt(i));
                }
                ((ViewGroup) view).removeAllViews();
        }
}

mainLayout 是活动布局的根视图。

mainLayout is the root view of the Activity layout.

我包含的onDestroy(),因为我可以手动完成()我的活动。

I include onDestroy() since I might manually finish() my Activity.

请注意。调用System.gc()是一个复杂的课题,您可以要忽略它。还有,为什么它可能不是一个很好的事情,主要涉及的性能就到这里一些很好的讨论。然而,在我看来,当一个活动被破坏,现在暗示这是一个很好的时间来执行GC可以做任何伤害。称这是不必要的将丢失破坏活动的管理费用的低效率。

Note. Calling system.gc() is a complex subject and you might want to omit it. There are some good discussions on here why it might not be a good thing to do, principally concerned with performance. However, in my view, when an activity is being destroyed, hinting that now is a good time to perform GC can do no harm. The inefficiency of calling it unnecessarily will be lost in the overheads of destroying an activity.

这篇关于正确的onDestroy()/如何避免内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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