2014-10-07 123 views
6

我发现文中的"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将从 资源中重新加载应用程序的用户界面。

所以上面的代码:

...泄漏在第一屏幕方向变化所造成的第一个活动。将Drawable附加到视图时,将视图 设置为drawable上的回调。在上面的代码段,这 意味着绘制有TextView的引用,其本身具有 参考活动(上下文),这反过来有引用 到几乎任何东西(取决于你的代码。)

但是,当屏幕方向的变化,该方法setBackgroundDrawable(Drawable background)被调用,进而调用:

background.setCallback(this); 

的方法Drawable.setCallback()以下列方式为definied:

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

所以,现在背景应该释放旧的引用到以前的TextView,并且应该创建对新的TextView的新引用。

因此,好像更改屏幕方向会泄漏参考,直到新创建活动为止。

我哪里错了?

+2

除了正确的答案之外,在活动中看到一个静态应该会让你本能地感到不适(参见'code smells')并将'this',或者'Context'或其他引用一个Activity的东西传递给对象,你不能直接控制它的生命周期,并且**保证**,至多,只要'活动',应该让你在现场呕吐。 – Simon 2014-10-07 20:39:19

+0

是的,清楚。谢谢@Simon – GVillani82 2014-10-07 20:44:22

+0

Romain Guy在原始[博客文章](http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on)的评论中解释了内存泄漏的场景-Android /)。 – corsair992 2014-10-07 21:42:22

回答

11

你是对的。然而,有一个微妙的一点:该文章是从。那时,的setCallback的实施是different

的Android < = 2.3.7:

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

的Android> = 4.0.1:

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

Grepcode没有显示出中间版本的源代码,这是我可以快速找到的唯一区别。


所以,再一次,你在这个特定的情况下,绝对正确(如果你的目标> 14即是)。然而,当你保持对这些项目的静态引用时(像你所做的那样),真正思考实际发生的事情仍然非常重要。有很多情况下你肯定可能会泄漏Context

+0

正是我正在检查 – njzk2 2014-10-07 20:36:04

+2

你是对的!谢谢你的答案 – GVillani82 2014-10-07 20:39:07