Android - 主线程处理程序是否会导致内存泄漏?

10
我很好奇为什么下面这段代码会造成内存泄漏,因为mHandler是在主线程上创建的,现在当onDestroy被调用时,它不会只是杀死线程吗?handler如何在activity销毁后还存在?我没有新建线程。我应该了解到,如果handler有消息队列中的内容,即使线程被销毁,它也会继续存在吗?
我正在阅读的参考文献在这里enter image description here
2个回答

19

Handler主要用于将事件发布到线程的消息队列中。每个Handler实例都与单个线程及其消息队列相关联。

因此,当您使用延迟时间发布可运行对象,并退出活动时,如果消息队列中仍有待处理的事件,将不会销毁MainThread。这可能会导致内存泄漏,因为您的匿名内部类runnable持有活动实例的引用。

因此,请确保在Activity的onStop()中调用并删除所有消息。

handler.removeCallbacksAndMessages(null);

在离开您的活动之前,这将清除所有未处理的消息和回调。


那么你的意思是,如果处理程序在队列中有消息,即使它被创建的活动已经完成,它也必须继续运行,对吗? - j2emanue
在我的例子中,处理程序与mainThread相关联。我正在将runnables发布到主线程的looper。现在,当活动调用onDestroy时,由于仍然存在于mainThreads looper队列中的消息,GC将不会收集该活动?还是因为runnable保留的引用,GC将不会收集该活动?你明白我的意思吗?假设runnable没有活动引用?它仍然会泄漏吗? - j2emanue
@j2emanue 如果你的可运行对象没有持有任何活动引用,那么就不会发生活动泄漏,但是主线程仍然会保持活跃状态,因为它必须完成由可运行对象发布到消息队列中的事件。 - Hasif Seyd
所以,即使你使用以下方式:private static Handler test = new Handler(Looper.getMainLooper());和test.postdelay(runnable,delayTime);在Activity中以delayTime为时间间隔发布runnable,这可能会导致内存泄漏,对吗?换句话说,runnable会持有Activity的实例。因此,即使你关闭了Activity,但消息(作为runnable)仍然挂起在MessageQueue中。 - Chinese Cat
有没有可能在不手动删除消息的情况下处理UI任务(包括在BaseActivity的onDestory中删除它),并确保没有内存泄漏? - Chinese Cat
显示剩余2条评论

0

它们可以,但不是Handler或Runnable的处理程序。 Handler的工作方式是与线程相关联的。该线程必须具有Looper。 Looper具有消息队列。当您postDelayed时,将Runnable添加到该Looper的消息队列中。因此,线程本身具有对Runnable的引用。因此,该Runnable将被泄漏,并且如果非静态,则父类也将被泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接