如何/何时处理垃圾回收?

在我的一个类中,我有以下代码:

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

每个Handler实例都与单个线程和该线程的消息队列相关联

所以如果我理解正确的话,只要应用程序线程正在运行,处理程序就不会被垃圾回收,那是对的吗?

在我的具体例子中,由于Handler是一个匿名的内部类,它有一个对封闭对象的隐式引用以及它所指向的整个对象的层次结构。 这在我看来就像一个泄漏内存的秘诀。

顺便说一句,我可以使处理程序停止发送消息(这就是为什么我有if (!paused) ),但这不会使它被GCed,对不对?

那么有没有办法从消息队列中删除处理程序,并得到它被GCed?

Solutions Collecting From Web of "如何/何时处理垃圾回收?"

在我的具体例子中,由于Handler是一个匿名的内部类,它有一个对封闭对象的隐式引用以及它所指向的整个对象的层次结构。

通过使用static嵌套类而不是匿名内部类,可以将潜在泄漏的影响降低到几乎没有。

处理程序源的检查揭示了更多的细节。

下面是由Romain Guy添加的Handler()构造函数的一些debugging代码:

 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的循环是从一个静态的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 – 除非它是一个具有WeakReference的静态嵌套类 – 将保留你的Activity和它的Activity观点。

你可以尝试通过清理你的消息来堵塞这个漏洞:

 handler.removeMessages(what); 

但说起来容易做起来难。

另请参阅Java和Android中的内存泄漏

不,停止发送消息不会使GC工作。 正如文档指出的,它绑定到创build它的线程。 如果线程正在运行,处理程序将不会被GC回收。

你为什么认为这可能会导致内存泄漏? 你是什​​么意思“隐式引用封闭的对象”?