匿名处理程序或Runnable会造成内存泄漏吗?

时间:2013-07-21 23:39:50

标签: java android memory-leaks

new Handler().postDelayed(new Runnable(){

@Override
public void run() {
     // do stuff
}}, 100);

如果我从一个活动(onCreate或onResume或其他地方)调用它,这会导致内存泄漏吗?我已经读过new Runnable()实际上应该是一个静态实例,是真的吗?

2 个答案:

答案 0 :(得分:6)

是。此代码可能会导致内存泄漏。

只要基于Runnable的匿名类在队列中(本例中为100毫秒),它就会保留对外部Activity类的引用。

当然,这样的内存泄漏本身并不是一个问题,但是根据执行run内部的代码,可能会产生更大的问题,例如在您执行时崩溃应用程序尝试在Activity被杀后显示对话框。在这种情况下,您将看到很好的信息例外:

  

IllegalArgumentException:onSaveInstanceState后无法执行此操作

  

BadTokenException:无法添加窗口 - ...您的活动正在运行吗?

答案 1 :(得分:2)

是的,这是泄漏。由于处理程序的工作方式,它们可以在很长一段时间内保持活动状态,并防止它们引用的任何资源被垃圾收集。这是一个很好的解释:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

如果您的runnable可能比您的对象的生命周期更长,请在此处的答案中尝试方法:https://stackoverflow.com/a/27825703/579234

您正在做的是在通常情况下添加另一级别的对象,触发关于非静态处理程序类的现有Lint警告将触发Lint警告:Android lint checks

HandlerLeak
-----------
Summary: Ensures that Handler classes do not hold on to a reference to an
outer class

Priority: 4 / 10
Severity: Warning
Category: Performance

In Android, Handler classes should be static or leaks might occur. Messages
enqueued on the application thread's MessageQueue also retain their target
Handler. If the Handler is an inner class, its outer class will be retained as
well. To avoid leaking the outer class, declare the Handler as a static nested
class with a WeakReference to its outer class.

使用匿名类与http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5中所述的相同:

  

匿名类始终是内部类(第8.1.3节);它永远不会是静态的(§8.1.1,§8.5.1)。

因此,为了明确解释,你的runnable持有对'this'的引用,并且处理程序保存对runnable的引用,因此在处理程序死亡之前,'this'不会被垃圾收集。