GVi*_*i82 6 java android memory-leaks android-layout android-view
我发现文章"避免内存泄漏",据说下面的代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
不是一个好主意,因为:
当屏幕方向改变时,系统默认会破坏当前活动并创建新活动,同时保留其状态.这样,Android将从资源重新加载应用程序的UI.
那么上面的代码:
...泄漏第一次屏幕方向更改时创建的第一个活动.将Drawable附加到视图时,视图将设置为drawable上的回调.在上面的代码片段中,这意味着drawable具有对TextView的引用,TextView本身具有对活动(Context)的引用,而Activity又引用了几乎所有内容(取决于您的代码).
但是,当屏幕方向改变时,调用方法setBackgroundDrawable(Drawable background),然后调用:
background.setCallback(this);
Run Code Online (Sandbox Code Playgroud)
该方法Drawable.setCallback()
以下列方式定义:
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
Run Code Online (Sandbox Code Playgroud)
因此,现在后台应该释放对前一个TextView的旧引用,并且应该创建对新TextView的新引用.
因此,似乎更改屏幕方向只会泄漏参考,直到新创建活动.
我哪里错了?
nha*_*man 11
你是绝对正确的.但是,有一个微妙的观点:文章来自2009年.那时候,执行情况setCallback
有所不同:
Android <= 2.3.7:
public final void setCallback(Callback cb) {
mCallback = cb;
}
Run Code Online (Sandbox Code Playgroud)
Android> = 4.0.1:
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
Run Code Online (Sandbox Code Playgroud)
Grepcode没有显示中间版本的源代码,这是我能够快速找到的唯一差异.
所以,再次,你在这个特定的情况下是完全正确的(如果你的目标是> 14).但是,当你对这些项目保持静态引用时(如你所做的那样),真正考虑实际发生的事情仍然非常重要.在很多情况下你肯定会泄漏Context
.