我正在开发一个带有服务的Android 2.3.3应用程序 . 我在服务中有这个与Main活动进行通信:
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());
[ ... ]
}
在这里, final Messenger mMessenger = new Messenger(new IncomingHandler());
,我得到以下Lint警告:
This Handler class should be static or leaks might occur: IncomingHandler
这是什么意思?
6 回答
这种方式对我来说效果很好,通过保持在自己的内部类中处理消息的位置来保持代码清洁 .
您要使用的处理程序
内在的阶级
如果
IncomingHandler
类不是静态的,它将引用您的Service
对象 .同一个线程的
Handler
对象都共享一个公共的Looper对象,它们将消息发送到该对象并从中读取 .由于消息包含目标
Handler
,只要消息队列中存在具有目标处理程序的消息,就不能对处理程序进行垃圾回收 . 如果处理程序不是静态的,那么即使在被销毁之后,您的Service
或_2615550也不会被垃圾收集 .这可能导致内存泄漏,至少在一段时间内 - 只要消息留在队列中 . 除非您发布长时间延迟的消息,否则这不是什么大问题 .
您可以将
IncomingHandler
设为静态并为您的服务设置WeakReference
:请参阅Romain Guy的这个post以获得进一步的参考
正如其他人所提到的,Lint警告是因为潜在的内存泄漏 . 您可以通过在构造
Handler
时传递_2615555来避免Lint警告(即,您没有子类Handler
且没有Handler
非静态内部类):据我了解,这不会避免潜在的内存泄漏 .
Message
对象包含对mIncomingHandler
对象的引用,该对象包含对Handler.Callback
对象的引用,该对象包含对Service
对象的引用 . 只要Looper
消息队列中有消息,Service
就不会是GC . 但是,除非您在消息队列中有长延迟消息,否则它不会是一个严重的问题 .下面是使用弱引用和静态处理程序类来解决问题的一般示例(如Lint文档中所建议的):
在@Sogger的回答的帮助下,我创建了一个通用的Handler:
界面:
我正在使用它如下 . 但我不能100%确定这是否是泄漏安全的 . 也许有人可以对此发表评论:
我不确定但是你可以在onDestroy()中尝试初始化处理程序为null