根据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个活动的应用程序,这是最长寿命的对象,可以根据需要重新创建.这意味着它的所有实例字段(可以且通常是View
s)在任何时候都可以为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()
sBackground
是null
,所以你给它分配getDrawable()
结果
您的活动UI将显示在屏幕上
使用者打喷嚏并意外地旋转装置的屏幕,作为对打喷嚏起反应的一部分
您的旧活动实例已被销毁
创建一个新的活动实例,然后调用它 onCreate()
sBackground
是不是null
,所以你离开sBackground
独自
你有泄漏.正如Romain所解释的那样,sBackground
对原始活动实例有一个非常明显的引用.因此,现在您有两个此活动的未完成实例:泄漏的原始文件,以及由于配置更改而创建的新原始实例.
假设应用程序具有1个活动,则这是最长寿命的对象
不它不是.您的流程中还有其他对象(例如Application
,内容提供商)将比活动实例更长久.
特别要注意的是,默认情况下,在配置更改(例如,屏幕旋转)时,活动会被销毁并重新创建.
并且任何静态实例字段将与活动本身持续相同的持续时间.
不会.只要流程在周围,静态字段就会出现.您的活动实例可能比这更短.
那么我们如何使用上面或下面的代码来获取内存泄漏:
您的第一个示例中没有静态字段.
Romain Guy解释了您链接到的博客文章中的第二个场景:
这段代码非常快,也非常错误; 它泄漏了第一次屏幕方向更改时创建的第一个活动.将Drawable附加到视图时,视图将设置为drawable上的回调.在上面的代码片段中,这意味着drawable具有对TextView的引用,TextView本身具有对活动(Context)的引用,而Activity又引用了几乎所有内容(取决于您的代码).
而且,如果您将LeakCanary添加到项目中,您会看到泄漏.
那么,让我们来看看:
用户点击您应用的主屏幕启动器图标,该图标与此活动相关联
您的流程已开始
您的活动实例已创建,然后随之调用 onCreate()
sBackground
是null
,所以你给它分配getDrawable()
结果
您的活动UI将显示在屏幕上
使用者打喷嚏并意外地旋转装置的屏幕,作为对打喷嚏起反应的一部分
您的旧活动实例已被销毁
创建一个新的活动实例,然后调用它 onCreate()
sBackground
是不是null
,所以你离开sBackground
独自
你有泄漏.正如Romain所解释的那样,sBackground
对原始活动实例有一个非常明显的引用.因此,现在您有两个此活动的未完成实例:泄漏的原始文件,以及由于配置更改而创建的新原始实例.