2013-07-21 110 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'不會被垃圾收集,直到處理程序死亡。