了解Android应用程序中的内存泄漏

时间:2014-10-07 20:22:03

标签: java android android-layout memory-leaks android-view

我找到了文章"Avoiding memory leaks",其中包含以下代码:

private static Drawable sBackground;

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

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

  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);

  setContentView(label);
}

不是一个好主意,因为:

  

当屏幕方向改变时,系统默认情况下会   破坏当前活动并创建一个新活动,同时保留它   州。这样,Android将从中重新加载应用程序的UI   资源。

所以上面的代码:

  

...泄漏在第一次屏幕方向更改时创建的第一个活动。将Drawable附加到视图时,视图为   设置为drawable的回调。在上面的代码片段中,这个   表示drawable引用了TextView,它本身就有一个   对活动(上下文)的引用,后者又引用了引用   几乎任何东西(取决于你的代码。)

但是,当屏幕方向发生变化时,会调用方法setBackgroundDrawable(Drawable background),然后调用:

background.setCallback(this);

方法Drawable.setCallback()的定义如下:

public final void setCallback(Callback cb) {
    mCallback = new WeakReference<Callback>(cb);
}

因此,现在后台应该释放对前一个TextView的旧引用,并且应该创建对新TextView的新引用。

因此,在新创建活动之前,更改屏幕方向似乎只会泄漏引用。

我哪里错了?

1 个答案:

答案 0 :(得分:11)

你是对的。但是,有一个微妙的观点:文章来自 2009 。那时候,setCallback的实施是different

Android&lt; = 2.3.7:

public final void setCallback(Callback cb) {
    mCallback = cb;
}

Android&gt; = 4.0.1:

public final void setCallback(Callback cb) {
    mCallback = new WeakReference<Callback>(cb);
}

Grepcode没有显示中间版本的源代码,这是我能够快速找到的唯一差异。


所以,再次,你在这个特定的情况下是完全正确的(如果你的目标是&gt; 14)。但是,当你对这些项目保持静态引用时(如你所做的那样),真正考虑实际发生的事情仍然非常重要。在很多情况下,你肯定会泄漏Context