在启动时,我的JavaFX应用程序会触发两个后台任务,一个用于初始化数据库,另一个用于对电子邮件服务器进行身份验证。每个任务都有一个布尔属性,指示成功完成。一旦这两项任务都完成了,我想开始第三项任务,开始对新邮件进行轮询。
我想我可以使用javafx.beans.binding.Bindings.and()来组合这两个任务的结果,但它不是激发。下面是一些代码:
BooleanBinding databaseInitializedProperty = NotesLocalDatabase.initializationStateProperty().isEqualTo( State.SUCCEEDED );
BooleanProperty isLoggedInProperty = loginPanel.isLoggedInProperty();
databaseInitializedProperty.addListener( (value, oldVal, newVal ) -> {
if( newVal ) log.info( "DATABASE INITIALIZED" ); } );
isLoggedInProperty.addListener( (value, oldVal, newVal ) -> {
if( newVal ) log.info( "IS LOGGED IN" ); } );
Bindings.and( databaseInitializedProperty, isLoggedInProperty ).addListener( (value, oldVal, newVal) -> {
log.info( "COMPOUND BINDING CHANGED: " + value + ", " + oldVal + ", " + newVal );
if( newVal ) {
log.info( "Login and database initialization both complete. Starting message check service." );
startUpdates();
}
} );我知道我的属性工作正常,因为我在日志中看到了“数据库初始化”和“登录”。然而,我从来没有看到“复合绑定改变”。通过阅读文档,我的印象是,Bindings.and()绑定上的更改侦听器在任何一个属性更改时都会被触发。不是这样的吗?
发布于 2014-10-22 16:36:11
您正在遇到另一个版本:Bidirectional JavaFX Binding is destroyed by unrelated code
问题是,当属性发生变化时,Bindings.and(...)的结果已经超出了范围。这使得它有资格进行垃圾收集。假设您的任务占用了足够多的内存来强制垃圾收集器运行,这样绑定就会被销毁,这并不是不合理的。
对于一个简单的示例,使用和不调用System.gc();运行以下命令
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
public class BindingTest {
public static void main(String[] args) {
BooleanProperty x = new SimpleBooleanProperty(false);
BooleanProperty y = new SimpleBooleanProperty(false);
x.addListener((obs, oldX, newX) -> System.out.printf("x changed from %s to %s%n", oldX, newX));
y.addListener((obs, oldY, newY) -> System.out.printf("y changed from %s to %s%n", oldY, newY));
Bindings.and(x, y).addListener((obs, oldXAndY, newXAndY) -> System.out.printf("x&y changed from %s to %s%n", oldXAndY, newXAndY));
x.set(true);
// System.gc();
y.set(true);
}
}修复方法是强制绑定保持在作用域中。您可能需要(有些不自然地)在某个地方将它作为实例变量:
public class SomeClass {
private BooleanBinding initializationComplete ;
public void whereverYouHadThisCodeBefore() {
// ..
initializationComplete = Bindings.and(databaseInitializedProperty, isLoggedInProperty);
initializationComplete.addListener(...);
}
}https://stackoverflow.com/questions/26512181
复制相似问题