Reputation: 5975
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
// do stuff
}}, 100);
If I call this from an activity (onCreate or onResume or elsewhere) can this cause a memory leak? I've read that the new Runnable()
should actually be a static instance, is that true?
Upvotes: 2
Views: 1883
Reputation: 16132
Yes this is a leak. Because of the way Handlers work it is possible for them to stay alive for very long periods of time and prevent any resources they reference from being garbage collected. Here is a good explantion: http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html
If your runnable may outlive the lifetime of your object, instead try the approach in the answer here: https://stackoverflow.com/a/27825703/579234
What you are doing is adding another level of object on top of the usual case that would trigger the existing Lint warning about non-static handler classes will trigger a Lint warning: 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.
Using an anonymous class is the same thing as stated in http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5:
An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).
So, to explain explicitly, your runnable holds a reference to 'this' and the handler holds a reference to the runnable so 'this' won't be garbage collected until the handler is dead.
Upvotes: 3
Reputation: 22232
Yes. This code may cause a memory leak.
For as long as this anonymous class based on Runnable
is in the queue (100 milliseconds in this example), it keeps a reference to outer Activity
class.
Such a memory leak is not a problem by itself of course, but depending on what code inside run
is executed, it may create bigger problems, like crashing the application when you e.g. try to show dialog after Activity
is killed. In such situations you will see nice informational exceptions:
IllegalArgumentException: Can not perform this action after onSaveInstanceState
or
BadTokenException: Unable to add window - ... is your activity running?
Upvotes: 6