我的活动代码如下
Handler handler = new Handler(){
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
}
};
Android Studio lint:
处理程序引用泄漏
由于此Handler被声明为内部类,因此可能会阻止外部类被垃圾回收。 如果Handler对主线程以外的线程使用Looper或MessageQueue,则没有问题。如果Handler正在使用主线程的Looper或MessageQueue,则需要修复处理程序声明如下:将Handler声明为静态类;在外部类中,实例化外部类的WeakReference,并在实例化Handler时将此对象传递给Handler;使用WeakReference对象对外部类的成员进行所有引用。
我知道Handler引用泄漏,因为它拥有强大的活动引用,并且活动无法通过垃圾收集来收集,但为什么Handler泄漏问题不会在主线程以外的线程中发生?主线程生命周期与应用程序一样重要吗?
答案 0 :(得分:1)
如果查看Handler实现,那么您将看到最初它没有将自己的引用传递给任何外部(即Looper)对象。一旦您post收到消息,this
引用被分配给消息target
字段,它就会在其外部传递参考。现在,如果您的消息是长期存在的(它的发布时间较长),那么它可能比您的Activity生命周期长,从而导致资源泄漏。实际原因是主线程消息队列,它包含一个引用处理程序的消息,该处理程序还包含对您的活动的引用。当您的处理程序在您的活动中处于内部静态时,会发生此引用泄漏。
因此现在让我们将主线程消息队列替换为其他一些线程消息队列。因为这是此警告消息所说的内容。假设你的处理程序仍然是你的活动的内部静态,但它使用了一些其他线程的looper,假设你想要有一些延迟发布消息到这个线程。一旦你的延迟消息进入这个工作线程的消息队列,它仍然会导致引用泄漏 - 它将无限期地保留对你的处理程序的引用,这也会引用你的活动。
所以我的理解是,在上面的场景中,这种警告并不完全正确。或许我错过了一些东西。
你可以争辩说一旦调用了Activity.onDestroy就可以终止这个线程,这当然会阻止引用泄漏。
答案 1 :(得分:0)
Android Studio lint在 Looper或MessageQueue中讲述了Handler 。 来自Android docs的示例:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
这显然没有任何活动的参考,因此没有泄漏。