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

标签 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);
}

这不是一个好主意,因为:

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/

相关文章:

java - 如何在 setText() 之后将文本附加到 TextView?

Android 服务交换总是崩溃

java - 在不覆盖其现有内容的情况下向 tar 文件添加条目

java - Android 中的自定义最大 asyncTasks

java - 查找列表是否包含相同的数据?

java - Android:我们可以为Grid-view item 一次设置多个标签吗?

android - 如何从 fragment 列表中的 EditText 获取用户输入?

android - 单击按钮打开应用程序中的 URL

android - 我怎样才能使 RelativeLayout 适合屏幕?

android - 动态 fragment 中的布局