当前位置:  开发笔记 > 编程语言 > 正文

为什么对Context的引用是内存泄漏?

如何解决《为什么对Context的引用是内存泄漏?》经验,为你挑选了1个好方法。

根据Romain Guy的说法,这种代码很容易因内存泄漏而导致

......观点提到了整个活动,因此也提到了你的活动所持有的任何内容; 通常是整个View层次结构及其所有资源.

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

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

  setContentView(label);
}  

我不清楚这一点.
假设具有1个活动的应用程序,这是最长寿命的对象,可以根据需要重新创建.这意味着它的所有实例字段(可以且通常是Views)在任何时候都可以为null.
并且任何静态实例字段将与活动本身持续相同的持续时间.
那么我们如何使用上面或下面的代码来获取内存泄漏:

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

CommonsWare.. 10

假设应用程序具有1个活动,则这是最长寿命的对象

不它不是.您的流程中还有其他对象(例如Application,内容提供商)将比活动实例更长久.

特别要注意的是,默认情况下,在配置更改(例如,屏幕旋转)时,活动会被销毁并重新创建.

并且任何静态实例字段将与活动本身持续相同的持续时间.

不会.只要流程在周围,静态字段就会出现.您的活动实例可能比这更短.

那么我们如何使用上面或下面的代码来获取内存泄漏:

您的第一个示例中没有静态字段.

Romain Guy解释了您链接到的博客文章中的第二个场景:

这段代码非常快,也非常错误; 它泄漏了第一次屏幕方向更改时创建的第一个活动.将Drawable附加到视图时,视图将设置为drawable上的回调.在上面的代码片段中,这意味着drawable具有对TextView的引用,TextView本身具有对活动(Context)的引用,而Activity又引用了几乎所有内容(取决于您的代码).

而且,如果您将LeakCanary添加到项目中,您会看到泄漏.

那么,让我们来看看:

用户点击您应用的主屏幕启动器图标,该图标与此活动相关联

您的流程已开始

您的活动实例已创建,然后随之调用 onCreate()

sBackgroundnull,所以你给它分配getDrawable()结果

您的活动UI将显示在屏幕上

使用者打喷嚏并意外地旋转装置的屏幕,作为对打喷嚏起反应的一部分

您的旧活动实例已被销毁

创建一个新的活动实例,然后调用它 onCreate()

sBackground 是不是null,所以你离开sBackground独自

你有泄漏.正如Romain所解释的那样,sBackground原始活动实例有一个非常明显的引用.因此,现在您有两个此活动的未完成实例:泄漏的原始文件,以及由于配置更改而创建的新原始实例.



1> CommonsWare..:

假设应用程序具有1个活动,则这是最长寿命的对象

不它不是.您的流程中还有其他对象(例如Application,内容提供商)将比活动实例更长久.

特别要注意的是,默认情况下,在配置更改(例如,屏幕旋转)时,活动会被销毁并重新创建.

并且任何静态实例字段将与活动本身持续相同的持续时间.

不会.只要流程在周围,静态字段就会出现.您的活动实例可能比这更短.

那么我们如何使用上面或下面的代码来获取内存泄漏:

您的第一个示例中没有静态字段.

Romain Guy解释了您链接到的博客文章中的第二个场景:

这段代码非常快,也非常错误; 它泄漏了第一次屏幕方向更改时创建的第一个活动.将Drawable附加到视图时,视图将设置为drawable上的回调.在上面的代码片段中,这意味着drawable具有对TextView的引用,TextView本身具有对活动(Context)的引用,而Activity又引用了几乎所有内容(取决于您的代码).

而且,如果您将LeakCanary添加到项目中,您会看到泄漏.

那么,让我们来看看:

用户点击您应用的主屏幕启动器图标,该图标与此活动相关联

您的流程已开始

您的活动实例已创建,然后随之调用 onCreate()

sBackgroundnull,所以你给它分配getDrawable()结果

您的活动UI将显示在屏幕上

使用者打喷嚏并意外地旋转装置的屏幕,作为对打喷嚏起反应的一部分

您的旧活动实例已被销毁

创建一个新的活动实例,然后调用它 onCreate()

sBackground 是不是null,所以你离开sBackground独自

你有泄漏.正如Romain所解释的那样,sBackground原始活动实例有一个非常明显的引用.因此,现在您有两个此活动的未完成实例:泄漏的原始文件,以及由于配置更改而创建的新原始实例.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有