如何解决当 ChangeListener 被输入为 lambda 时,JavaFX 中的 addListener 是否会被垃圾收集? 示例何时使用弱监听器事件处理程序
我意识到我的项目使用了大量 JavaFX ChangeListeners
来跟踪某些条件。
我很确定在与 property.addListener(ChangeListener)
一起使用时侦听器不会被垃圾收集,但是如果我将我的侦听器置于 lambda 形式而不是首先声明它们,它们仍然不会被垃圾收集吗?
示例:
field.focusedProperty().addListener((obs,oldVal,newVal) -> {
// Do stuff
}
});
顺便说一句,当我关闭程序时,所有侦听器都被清除了还是继续存在?
解决方法
监听器会被垃圾收集吗?
只要注册到 observable 的侦听器就不会被垃圾收集。当然,假设有对 observable 的强烈引用。这是因为 observable 保持对每个注册的侦听器的强引用。事实上,如果您不小心,这可能是您的应用程序内存泄漏的原因。这就是为什么我们有:
弱监听器
为了使您的应用程序更能抵抗内存泄漏,您可以使用 WeakListener
的实现。为您提供了五种公共实现:
WeakInvalidationListener
WeakChangeListener
WeakListChangeListener
WeakSetChangeListener
WeakMapChangeListener
这些实现将其相应的侦听器包装起来并将其保存在 WeakReference
中。这样 observable 只对弱侦听器有很强的引用,而不是“真正的”侦听器。这就是为什么你必须在需要时自己保持对“真实”侦听器的强引用,否则它会过早被垃圾收集。
示例
以下是使用弱侦听器的示例:
import javafx.beans.value.ChangeListener;
import javafx.beans.value.WeakChangeListener;
import javafx.scene.Node;
public class Foo {
// strong reference to "real" listener
private final ChangeListener<Boolean> focusListener =
(obs,oldVal,newVal) -> {
// do something...
};
private final Node node;
public Foo(Node node) {
this.node = node;
node.focusedProperty().addListener(new WeakChangeListener<>(focusListener));
}
}
如果您需要能够随意删除弱侦听器,那么您还需要保留对它的引用。
何时使用弱监听器
当您不能保证不再需要监听器时,您应该使用弱监听器。如果侦听器捕获对其他对象的引用(例如上面示例中的 Foo
实例),这一点尤其重要。
如果 observable 和 listener 可以保证在相对相同的时间被垃圾回收,请不要使用弱侦听器。例如,如果 Foo
有一个属性并为该属性本身添加一个侦听器(例如 this.someProperty().addListener((...) -> {...})
),那么当 Foo
实例为垃圾收集。
此外,如果出现以下情况,使用弱监听器可能会比它们的价值更费力:
- 您的应用程序是微不足道的或相对短暂的。
- 您的应用程序是相对静态的(即不会连续创建和丢弃您注册侦听器的对象)。
如果不确定,您总是可以走非弱路线开始,只有在您分析问题时才更改为弱听众。
事件处理程序
此处描述的所有内容对 EventHandler
和 WeakEventHandler
的作用相同。请注意,后者没有实现 WeakListener
。
Lambda 表达式
使用 lambda 表达式来实现侦听器(或处理程序)会改变什么吗?与此上下文没有任何关系。一个 lambda 表达式只是一个函数接口的实现。通过 lambda 表达式创建的实例与其他任何实例一样。
应用退出时会发生什么?
当该进程退出时,分配给该进程的所有内存都会释放回操作系统。这意味着所有对象都不再存在于内存中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。