我知道如果我在Android中对Handler类进行子类化,最好是静态的,否则可能会发生内存泄漏。像这样:
static class MyHandler extends Handler {...}
但是如果我只是构建一个Handler类的对象呢?像这样:
Handler mHandler = new Handler();
它应该是静态的吗?像这样:
static Handler mHandler = new Handler();
由于默认的Handler将使用默认(主)线程,因此进程中只有一个主线程。 这是否意味着mHandler不应该是我的组件类中的非静态字段(即Activity,Receiver,...)? 感谢。
------------------更新更多信息--------------------- 谢谢你快速的回复。 但以下所有答案都不是我要问的。
问题是, 处理程序对象"附加"本身默认为一个进程。 (从技术上讲,它附加到主线程)
这意味着它的生命周期不附加到活动或接收者。
所以,如果我把它变成一个活动的非静态字段, 不是吗?
(我的问题更多"理论/逻辑",不是"实用")
答案 0 :(得分:1)
静态类无论如何也无法调用自身的实例。这实际上是静态的定义。你真正想知道的是如何清理非静态对象,这很容易。
Java虚拟机具有垃圾处理阶段,可定期检查对活动对象的引用。如果活动对象没有引用,JVM会将其扫描到垃圾箱中。
例如,如果您的处理程序位于代码块中,例如在while循环或函数或其他任何内容中,
{
Handler testHandler = new Handler();
}
当该块结束时,无法再访问testHandler。它没有参考它,垃圾处理将处理它。所以我不会太担心它,除非像一个无限循环,每个循环itteration能够在循环外的arrayList中创建一个新的Handler()因为那时Handler永远不会死,最终你会使用你所有的内存而你崩溃了。
但那些是必要的人为测试案例。它们并不经常发生,但我认为你可能正在制作游戏,如果你在询问记忆和Android,游戏有无限循环,这就是你需要注意的事情。
只需将对象设置为null即可删除对象。 null是一个特殊对象,根本没有实际引用,所以将变量设置为null是低内存。不幸的是,除非它在某些时候超出范围,否则会有一些内存用于存放变量的名称。但是在java中没有其他(好的)方法可以摆脱它。
答案 1 :(得分:1)
pskink在上面的评论中指出了以下(优秀)文章:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html
这对于Android开发人员(实际上对任何Java开发人员来说都是有价值的信息!):非静态的内部类保存(隐式)对外部类(Activity)的引用。因此,在内部类比外部类长寿的情况下,外部类在内部类之前不具备垃圾收集的条件。或换句话说 - 这可能导致内存泄漏!
在Android中,例如,配置更改可能导致活动对象被销毁并创建一个新对象。在这种情况下,如果处理程序(定义为内部非静态类)仍在运行 - GC将无法清除Activity对象。
以上所有内容与声明保存处理程序的变量的方式无关。该变量可以是静态的或非静态的:
关键字static
在不同的上下文中有不同的含义 - 所以当我们引用类变量时,将其设置为static
意味着它由该类的所有对象共享(与非静态变量不同 - 创建和访问的内容:每个对象一个。
回到前面的例子:将Handler保存为static的变量设置意味着只为Activity类创建一个这样的对象,所以即使配置更改生效并且Activity对象被销毁而新的对象也是如此已创建 - 新的将继续使用相同的(静态)处理程序。