2
new Handler().postDelayed(new Runnable(){

@Override
public void run() {
     // do stuff
}}, 100);

如果我从活动(onCreate 或 onResume 或其他地方)调用它,这会导致内存泄漏吗?我读过new Runnable()实际上应该是一个静态实例,是这样吗?

4

2 回答 2

6

是的。此代码可能会导致内存泄漏。

只要这个基于的匿名类Runnable在队列中(本例中为 100 毫秒),它就会保持对外部Activity类的引用。

这样的内存泄漏本身当然不是问题,但是根据run执行内部代码的不同,它可能会产生更大的问题,例如当您尝试在Activity被杀死后显示对话框时使应用程序崩溃。在这种情况下,您会看到很好的信息异常:

IllegalArgumentException:onSaveInstanceState 后无法执行此操作

或者

BadTokenException:无法添加窗口 - ...您的活动正在运行吗?

于 2013-07-21T23:57:32.920 回答
3

是的,这是一个泄漏。由于 Handlers 的工作方式,它们有可能在很长一段时间内保持活动状态,并防止它们引用的任何资源被垃圾收集。这是一个很好的解释:http ://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

如果您的可运行文件可能超过对象的生命周期,请尝试此处的答案中的方法:https ://stackoverflow.com/a/27825703/579234

您正在做的是在通常情况下添加另一个级别的对象,这将触发现有的关于非静态处理程序类的 Lint 警告将触发 Lint 警告:Android lint checks

处理程序泄漏
------------
摘要:确保 Handler 类不持有对
外层

优先级:4 / 10
严重性:警告
类别:性能

在 Android 中,处理程序类应该是静态的,否则可能会发生泄漏。留言
在应用程序线程的 MessageQueue 上排队也保留了它们的目标
处理程序。如果 Handler 是一个内部类,它的外部类将被保留为
出色地。为避免泄漏外部类,请将 Handler 声明为静态嵌套
具有对其外部类的 WeakReference 的类。

使用匿名类与http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5中所述相同:

匿名类始终是内部类(第 8.1.3 节);它永远不是静态的(§8.1.1、§8.5.1)。

因此,为了明确解释,您的可运行对象包含对“this”的引用,而处理程序持有对可运行对象的引用,因此在处理程序死亡之前不会对“this”进行垃圾收集。

于 2015-01-07T17:38:59.387 回答