该Handler类应该是静态的,否则可能会发生泄漏:IncomingHandler

本文翻译自:This Handler class should be static or leaks might occur: IncomingHandler

I'm developing an Android 2.3.3 application with a service. 我正在开发带有服务的Android 2.3.3应用程序。 I have this inside that service to communicate with Main activity: 我在服务内部拥有此功能,可与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());
    [ ... ]
}

And here, final Messenger mMessenger = new Messenger(new IncomingHandler()); 在这里, final Messenger mMessenger = new Messenger(new IncomingHandler()); , I get the following Lint warning: ,我收到以下Lint警告:

This Handler class should be static or leaks might occur: IncomingHandler

What does it mean? 这是什么意思?


#1楼

参考:https://stackoom.com/question/LRJ5/该Handler类应该是静态的-否则可能会发生泄漏-IncomingHandler


#2楼

If IncomingHandler class is not static, it will have a reference to your Service object. 如果IncomingHandler类不是静态的,则它将引用您的Service对象。

Handler objects for the same thread all share a common Looper object, which they post messages to and read from. 同一线程的Handler对象都共享一个公共的Looper对象,它们将消息发布到其中并从中读取。

As messages contain target Handler , as long as there are messages with target handler in the message queue, the handler cannot be garbage collected. 由于消息包含目标Handler ,因此只要消息队列中存在带有目标处理程序的消息,就无法对处理程序进行垃圾回收。 If handler is not static, your Service or Activity cannot be garbage collected, even after being destroyed. 如果处理程序不是静态的,则即使销毁了ServiceActivity也无法对其进行垃圾回收。

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: 您可以将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);
         }
    }
}

See this post by Romain Guy for further reference 请参阅Romain Guy的这篇文章,以获取更多参考


#3楼

As others have mentioned the Lint warning is because of the potential memory leak. 正如其他人提到的那样,Lint警告是由于潜在的内存泄漏。 You can avoid the Lint warning by passing a Handler.Callback when constructing Handler (ie you don't subclass Handler and there is no Handler non-static inner class): 您可以通过在构造Handler时传递Handler.Callback来避免Lint警告(即,您不Handler.Callback Handler且没有Handler非静态内部类):

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. Message对象包含对mIncomingHandler对象的引用,该对象包含对Handler.Callback对象的引用,该对象包含对Service对象的引用。 As long as there are messages in the Looper message queue, the Service will not be GC. 只要Looper消息队列中有消息,该Service就不会是GC。 However, it won't be a serious issue unless you have long delay messages in the message queue. 但是,除非您在消息队列中有很长的延迟消息,否则这将不是一个严重的问题。


#4楼

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 您要使用的处理程序

Handler mIncomingHandler = new Handler(new IncomingHandlerCallback());

The inner class 内在阶级

class IncomingHandlerCallback implements Handler.Callback{

        @Override
        public boolean handleMessage(Message message) {

            // Handle message code

            return true;
        }
}

#5楼

我不确定,但您可以尝试在onDestroy()中将处理程序初始化为null


#6楼

Here is a generic example of using a weak reference and static handler class to resolve the problem (as recommended in the Lint documentation): 这是使用弱引用和静态处理程序类解决问题的通用示例(如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);
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值