我找到了这篇文章 "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);
}
这不是一个好主意,因为:
When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources.
所以上面的代码:
...leaks the first activity created upon the first screen orientation change. When a Drawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)
但是,当屏幕方向改变时,方法setBackgroundDrawable(Drawable background)被调用,它又调用:
background.setCallback(this);
Drawable.setCallback()
方法定义如下:
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
因此,现在后台应该释放对先前 TextView 的旧引用,并且应该创建对新 TextView 的新引用。
因此,更改屏幕方向似乎只会在新创建 Activity 之前泄漏引用。
我哪里错了?
最佳答案
你完全正确。但是,有一点很微妙:这篇文章是 2009 的。那时,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
。
关于java - 了解 Android 应用程序中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26244593/