JavaFX中的Bindings.and()没有触发?

时间:2014-10-22 16:17:13

标签: javafx

启动时,我的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();
        }
    } );

我知道我的属性工作正常,因为我在日志中看到“DATABASE INITIALIZED”和“IS LOGGED IN”。但是,我从未见过“复合约束变更”。从阅读文档开始,我认为只要属性发生变化,就会触发Bindings.and()绑定上的更改侦听器。那不是这样吗?

1 个答案:

答案 0 :(得分:3)

您正在使用此版本的另一个版本: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(...);
    }
}