I'm developing an Android 2.3.3 application with a service. I have this inside that service to communicate with Main activity:
public class UDPListenerService extends Service
{
private static final String TAG = "UDPListenerService";
//private ThreadGroup myThreads = new ThreadGroup("UDPListenerServiceWorker");
private UDPListenerThread myThread;
/**
* Handler to communicate from WorkerThread to service.
*/
private Handler mServiceHandler;
// Used to receive messages from the Activity
final Messenger inMessenger = new Messenger(new IncomingHandler());
// Use to send message to the Activity
private Messenger outMessenger;
class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
}
}
/**
* Target we publish for clients to send messages to Incoming Handler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
[ ... ]
}
And here, final Messenger mMessenger = new Messenger(new IncomingHandler());
, I get the following Lint warning:
This Handler class should be static or leaks might occur: IncomingHandler
What does it mean?
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 constructingHandler
(i.e. you don't subclassHandler
and there is noHandler
non-static inner class):As I understand it, this will not avoid the potential memory leak.
Message
objects hold a reference to themIncomingHandler
object which holds a reference theHandler.Callback
object which holds a reference to theService
object. As long as there are messages in theLooper
message queue, theService
will not be GC. However, it won't be a serious issue unless you have long delay messages in the message queue.I am not sure but you can try intialising handler to null in onDestroy()
Here is a generic example of using a weak reference and static handler class to resolve the problem (as recommended in the Lint documentation):
With the help of @Sogger's answer, I created a generic Handler:
The interface:
I'm using it as follows. But I'm not 100% sure if this is leak-safe. Maybe someone could comment on this:
If
IncomingHandler
class is not static, it will have a reference to yourService
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, yourService
orActivity
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 aWeakReference
to your service:See this post by Romain Guy for further reference
This way worked well for me, keeps code clean by keeping where you handle the message in its own inner class.
The handler you wish to use
The inner class