Van*_*nel 287 android memory-leaks static-classes android-lint android-handler
我正在开发一个带有服务的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());
[ ... ]
}
Run Code Online (Sandbox Code Playgroud)
在这里,final Messenger mMessenger = new Messenger(new IncomingHandler());我得到以下Lint警告:
This Handler class should be static or leaks might occur: IncomingHandler
这是什么意思?
Tom*_*ski 384
如果IncomingHandlerclass不是静态的,它将引用您的Service对象.
Handler 同一个线程的对象都共享一个公共的Looper对象,它们将消息发送到该对象并从中读取.
由于消息包含目标Handler,只要消息队列中存在具有目标处理程序的消息,就不能对处理程序进行垃圾回收.如果处理程序不是静态的,即使在被销毁之后,您Service或者Activity也不能进行垃圾回收.
这可能导致内存泄漏,至少在一段时间内 - 只要消息留在队列中.除非您发布长时间延迟的消息,否则这不是什么大问题.
您可以制作IncomingHandler静态并WeakReference为您提供服务:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅Romain Guy的这篇文章以获得进一步的参考
Mic*_*ael 65
正如其他人所提到的,Lint警告是因为潜在的内存泄漏.您可以通过传递Handler.Callback构造时避免Lint警告Handler(即,您不是子类,Handler并且没有Handler非静态内部类):
Handler mIncomingHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// todo
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
据我了解,这不会避免潜在的内存泄漏.Message对象持有对象的引用,该mIncomingHandler对象保存Handler.Callback对象,该对象保存对象的引用Service.只要Looper消息队列中有消息,Service就不会是GC.但是,除非您在消息队列中有长延迟消息,否则它不会是一个严重的问题.
Sog*_*ger 32
下面是使用弱引用和静态处理程序类来解决问题的一般示例(如Lint文档中所建议的):
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Stu*_*ell 24
这种方式对我来说效果很好,通过保持在自己的内部类中处理消息的位置来保持代码清洁.
您要使用的处理程序
Handler mIncomingHandler = new Handler(new IncomingHandlerCallback());
Run Code Online (Sandbox Code Playgroud)
内在的阶级
class IncomingHandlerCallback implements Handler.Callback{
@Override
public boolean handleMessage(Message message) {
// Handle message code
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
130505 次 |
| 最近记录: |