在我的一个类中,我有以下代码:
mHandler = createHandler();
private Handler createHandler() {
return new Handler() {
public void handleMessage (Message msg) {
update();
if (!paused) {
sendEmptyMessageDelayed(0, 300);
}
}
};
}
文档说:
http://developer.android.com/reference/android/os/Handler.html http://developer.android.com/reference/android/os/Handler.html
每个 Handler 实例都与一个线程以及该线程的消息队列相关联
因此,如果我理解正确,只要应用程序线程正在运行,处理程序就不会被垃圾回收,这是正确的吗?
在我的具体示例中,由于 Handler 是一个匿名内部类,因此它具有对封闭对象及其所指向的整个对象层次结构的隐式引用。在我看来,这就像内存泄漏的秘诀。
顺便说一句,我可以让处理程序停止发送消息(这就是为什么我有if (!paused)
)但这不会使它成为 GCed,对吧?
那么有没有办法将Handler从消息队列中移除并让它被GC呢?
对 Handler 源代码的检查揭示了更多细节。
以下是 Romain Guy 添加的 Handler() 构造函数中的一些调试代码:
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
警告很明确:不要将 Handler 子类声明为内部类。
Handler的looper是从静态ThreadLocal实例中获取的:
mLooper = Looper.myLooper();
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
泄漏的剖析:
主应用程序线程保留 Looper 及其 MessageQueue,队列中的消息保留其目标 Handler 的链接,而 Handler(除非它是对您的 Activity 具有 WeakReference 的静态嵌套类)将保留您的 Activity 及其目标意见。
您可以尝试通过清理消息来堵塞此泄漏:
handler.removeMessages(what);
但这说起来容易做起来难。
另请参阅关于 Java 和 Android 中的内存泄漏 http://chaosinmotion.com/blog/?p=696
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)