This Handler class should be static or leaks might occur: IncomingHandler
If IncomingHandler
class is not static, it will have a reference to your Service
object.
Handler
objects for the same thread all share a common Looper object, which they post messages to and read from.
As messages contain target Handler
, as long as there are messages with target handler in the message queue, the handler cannot be garbage collected. If handler is not static, your Service
or Activity
cannot be garbage collected, even after being destroyed.
This may lead to memory leaks, for some time at least - as long as the messages stay int the queue. This is not much of an issue unless you post long delayed messages.
You can make IncomingHandler
static and have a WeakReference
to your service:
static class IncomingHandler extends Handler { private final WeakReference<UDPListenerService> mService; IncomingHandler(UDPListenerService service) { mService = new WeakReference<UDPListenerService>(service); } @Override public void handleMessage(Message msg) { UDPListenerService service = mService.get(); if (service != null) { service.handleMessage(msg); } }}
See this post by Romain Guy for further reference
As others have mentioned the Lint warning is because of the potential memory leak. You can avoid the Lint warning by passing a Handler.Callback
when constructing Handler
(i.e. you don't subclass Handler
and there is no Handler
non-static inner class):
Handler mIncomingHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { // todo return true; }});
As I understand it, this will not avoid the potential memory leak. Message
objects hold a reference to the mIncomingHandler
object which holds a reference the Handler.Callback
object which holds a reference to the Service
object. As long as there are messages in the Looper
message queue, the Service
will not be GC. However, it won't be a serious issue unless you have long delay messages in the message queue.
Here is a generic example of using a weak reference and static handler class to resolve the problem (as recommended in the Lint documentation):
public class MyClass{ //static inner class doesn't hold an implicit reference to the outer class private static class MyHandler extends Handler { //Using a weak reference means you won't prevent garbage collection private final WeakReference<MyClass> myClassWeakReference; public MyHandler(MyClass myClassInstance) { myClassWeakReference = new WeakReference<MyClass>(myClassInstance); } @Override public void handleMessage(Message msg) { MyClass myClass = myClassWeakReference.get(); if (myClass != null) { ...do work here... } } } /** * An example getter to provide it to some external class * or just use 'new MyHandler(this)' if you are using it internally. * If you only use it internally you might even want it as final member: * private final MyHandler mHandler = new MyHandler(this); */ public Handler getHandler() { return new MyHandler(this); }}