2013-07-21 75 views
2
new Handler().postDelayed(new Runnable(){ 

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

如果我从一个activity(onCreate或onResume或别的地方)调用这个会导致内存泄漏吗?我读过new Runnable()实际上应该是一个静态实例,这是真的吗?匿名处理程序或Runnable会造成内存泄漏吗?

+1

你已经读过它应该是一个静态*类。*匿名类不能是静态的,但是你不应该以这种方式使用它。但问题在于非静态性,而不是匿名性。 – EJP

回答

6

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

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

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

抛出:IllegalArgumentException:的onSaveInstanceState后

BadTokenException无法执行此操作:无法添加窗口 - ...是你的活动运行?

+0

我打算按照相同的方式发布答案。你认为从处理程序中移除回调会照顾到这个问题吗? – Vikram

+0

@vikram是的。我通常在'onPause'中移除'Runnable'。 –

+0

是的,这里也一样。 – Vikram

2

是的,这是一个泄漏。由于处理程序的工作方式,它们可以长时间保持活力,并防止他们参考的任何资源被垃圾收集。这里是一个很好explantion:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

如果您运行的可能活得比你的对象的生命周期,而不是尝试在回答这里的做法:https://stackoverflow.com/a/27825703/579234

你在做什么是添加对象的另一个层次上的顶部这将引发对非静态处理器类的现有皮棉警告通常情况下会触发皮棉警告: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'不会被垃圾收集,直到处理程序死亡。