- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我试图在控制器的initialize()方法中将TextArea的textProperty绑定到StringProperty。
值更改时,侦听器会监听这两个对象,以执行某些行为。
但是有些奇怪的事情发生了。
我建立了一个简单的模型来重现这种情况。
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.TextArea?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
prefHeight="300" prefWidth="400">
<TextArea fx:id="textArea"/>
</GridPane>
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
TextArea textArea;
private StringProperty toBind = new SimpleStringProperty();
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
}
}
textArea: a
textArea: ab
textArea: abc
textArea: abcd
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
TextArea textArea;
private StringProperty toBind = new SimpleStringProperty();
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
// ----- New statements. -----
System.out.print("toBind value in textArea: ");
System.out.println(toBind.get());
// ----- New statements. -----
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
}
}
toBind: a
textArea: a
toBind value in textArea: a
toBind: ab
textArea: ab
toBind value in textArea: ab
toBind: abc
textArea: abc
toBind value in textArea: abc
toBind: abcd
textArea: abcd
toBind value in textArea: abcd
最佳答案
您的绑定和toBind
属性正在被垃圾回收。
托马斯·米库拉(Tomas Mikula)在他的blog上对“过早的垃圾收集”问题进行了简要描述。
首先,对于任何试图重现此问题的人来说,请速记一点。由于所描述的行为取决于发生的垃圾回收,因此它可能并不总是发生(取决于内存分配,所使用的GC实现以及其他因素)。如果添加行
root.setOnMouseClicked(e -> System.gc());
start()
方法中,然后单击场景中的空白区域将请求垃圾回收,问题将(至少更有可能)在那之后(如果尚未出现)显现出来。
WeakListener
侦听属性更改并将这些更改传播到绑定的属性。如果没有其他 Activity 引用,弱侦听器的设计目的是不要阻止对其附加的属性进行垃圾回收。 (其基本原理是避免在属性不再在范围内时强迫程序员强制清理绑定。)
toBind
可以进行垃圾回收。
start()
方法完成后,可以保证拥有的所有引用都是调用
Application
时显示的
launch()
实例,显示的
Stage
以及从其中引用的所有内容。当然,这包括
Scene
(由
Stage
引用),其
root
,
root
的子代,它们的子代等,它们的属性以及这些属性中任何一个的(非弱)侦听器。
stage
引用了
scene
,后者引用了作为其根的
GridPane
,并且引用了
TextArea
。
TextArea
附加了对该侦听器的引用,但该侦听器未保留其他引用。
ChangeListener
的非弱
textArea.textProperty()
引用了
toBind
。因此,在该版本中,
ChangeListener
防止
toBind
进行GC,然后您可以在其上看到来自侦听器的输出。 )
FXMLLoader
创建控制器实例。虽然该控制器实例具有对string属性和文本区域的引用,但事实并非如此。因此,一旦加载完成,就没有对控制器的实时引用,并且可以对其进行定义的
StringProperty
进行垃圾回收。文本区域的
textProperty()
仅对
toBind
上的侦听器进行弱引用,因此,文本区域无法防止
toBind
被垃圾回收。
StringProperty
。因此,如果您添加以“自然”方式使用此代码的任何代码,则很可能会看到问题消失。
<Label fx:id="label" GridPane.rowIndex="1"/>
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
label.textProperty().bind(toBind);
}
textProperty
通过绑定到
toBind
而具有弱引用。由于
label
未进行GC处理,因此弱引用可幸免于垃圾回收,而
toBind
无法进行GC处理,因此您将看到期望的输出。
toBind
属性,例如在
Application
实例中:
public class Controller {
@FXML
TextArea textArea;
private StringProperty toBind = new SimpleStringProperty();
public void initialize() {
textArea.textProperty().bindBidirectional(toBind);
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.print("textArea: ");
System.out.println(newValue);
});
toBind.addListener((observable, oldValue, newValue) -> {
System.out.print("toBind: ");
System.out.println(newValue);
});
}
public StringProperty boundProperty() {
return toBind ;
}
}
package sample;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
private StringProperty boundProperty ;
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
Controller controller = loader.getController();
boundProperty = controller.boundProperty();
root.setOnMouseClicked(e -> System.gc());
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
textArea.textProperty()
上的侦听器:
textArea.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.print("textArea: ");
System.out.println(newValue);
}
});
toBind
的GC。原因是匿名内部类的实例包含对封闭实例的隐式引用(在这种情况下,即控制器的实例):此处,控制器保留对
toBind
的引用。相比之下,Lambda表达式则不这样做。
关于java - 如何将监听器添加到双向绑定(bind)的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48237645/
我有 2 个类:User 和 UserPicture,它们具有 1:1 关系。 public class User { @Id @GeneratedValue(strategy=G
使用ssh转发时,我无法针对远程服务器使用cvs和ftp进行提交。是否可以让服务器对我的机器发起请求-我希望服务器上的Web应用程序调用我的机器上的REST方法。 谢谢。 尼古拉·G。 最佳答案 是的
我正在 Python 2.7.12 中实现双向 A* 算法,并在 Russell 和 Norvig 第 3 章的罗马尼亚 map 上进行测试。边具有权重,目的是找到两个节点之间的最短路径。 这是测试图
您能否建议一种映射或类似的数据结构,让我们可以轻松地相互获取值和键。也就是说,每个都可以用来寻找另一个。 最佳答案 Java 在其标准库中没有双向映射。 例如使用 BiMap 来自Google Gua
我想同步两个数据库运行时 服务器 A:安装了公共(public) IP 和 mysql 的 Amazon ec2。服务器B:这是局域网中带有mysql的私有(private)机器。 (IP是私有(pr
保存双向@OneToOne 映射时,hibernate 是否应该在两个表上都记录? 我有一个包含 applicant_id 列的表 interview,它引用了包含字段 interview_id 的
我喜欢新的 SwipeRefreshLayout!它看起来很棒,而且非常容易使用。但我想在两个方向上使用它。我有一个消息屏幕,我想通过从上到下滑动来加载旧消息,我想通过从下到上滑动来加载新消息。 这个
使用 ICS 4.0.1(愿意升级到 4.0.3)(不会 root 和重写 android 操作系统) 在接收到 android beam 后,是否可以将 NDEF 消息发送回 android 手机
我想知道处理这种 git 场景的最佳方法: Git 仓库:CoreProduct Git repo b: SpecificCustomerProduct 是从 a fork 出来的 到目前为止,我们一
这个问题在这里已经有了答案: How to implement an efficient bidirectional hash table? (8 个回答) 关闭2年前。 我在 python 中做这个
您能否推荐一种 map 或类似的数据结构,我们可以在其中轻松地从彼此获取值和键。也就是说,每个都可以用来寻找另一个。 最佳答案 Java 在其标准库中没有双向映射。 例如使用 BiMap 来自 Goo
Java中是否有类似双面列表的东西?也许第三方实现? 这里有一个小例子来证明我的想法。 原始状态: 答:0-1-2-3 | | | | 乙:0-1-2-3 删除 B 中的元素 1 后: 空值 | 答:
我有两个实体通过这样的双向 OneToOne 关联连接: @Entity class Parent { @NotNull String businessKey; @OneToO
我已将 Vagrant 配置为使用 Rsync 共享文件夹而不是(非常慢)vboxsf VirtualBox 默认提供的文件系统: Vagrant.configure("2") do |config|
@keyframes mgm { from { max-height: 250px; } to { max-height: 0px; } } .mgm {
我想了解有关使用双向 LSTM 进行序列分类时合并模式的更多详细信息,尤其是对于我还不清楚的“Concat”合并模式。 根据我对这个方案的理解: 在将前向和后向层的合并结果传递到 sigmoid 函数
我有兴趣将本地 git 存储库设置为远程存储库的镜像。我已经阅读了一些可能相关的帖子,但主要区别在于我需要对两个存储库进行读写访问。 大多数时候,用户会针对 Repo A 工作,但是有时他们会针对 R
我已经仔细阅读了文档 https://firebase.google.com/docs/database/web/read-and-write以及网上很多例子。但这里有一个脱节:在将对象添加到数据库时
这个问题已经有答案了: Hibernate bidirectional @ManyToOne, updating the not owning side not working (3 个回答) 已关闭
我知道有很多关于它的问题,但我找不到针对我的问题的好的答案。 我使用 Jboss 作为 7,Spring 和 Hibernate (4) 作为 JPA 2.0 提供程序,因此我有简单的 @OneToM
我是一名优秀的程序员,十分优秀!