简体   繁体   English

布尔属性如何与createBooleanBinding一起使用

[英]How does boolean property work with createBooleanBinding

I have this code : 我有这个代码:

public class Test {
    public static void main(String [] args) {

        ObservableList<Integer> l = FXCollections.observableArrayList();
        l.add(1);
        l.add(2);
        l.add(3);
        BooleanProperty isPlayable = new SimpleBooleanProperty();
        isPlayable.bind(Bindings.createBooleanBinding(() -> 
        {
            System.out.println("List has changed");

            return l.contains(2);
        },l
        ));
l.remove(1);

I don't understand why would this code display "List has changed" only one time ? 我不明白为什么这段代码只能显示“列表已更改”? It should twice, one at the binding, and then in the remove because the list is observable. 它应该两次,一次在绑定中,然后在删除中,因为该列表是可观察的。 Why the list changement doesn't affect the boolean property ? 为什么列表更改不影响boolean属性?

(I have a bigger problem in the long code but this situation illustrates my misunderstanding of the boolean property bindings) (我在长代码中遇到了更大的问题,但是这种情况说明了我对布尔型属性绑定的误解)

Thank you ! 谢谢 !

From the documentation of ObservableValue (which both Binding and Property inherit from): ObservableValue文档中( BindingProperty都从该文档继承):

An implementation of ObservableValue may support lazy evaluation, which means that the value is not immediately recomputed after changes, but lazily the next time the value is requested. ObservableValue的实现可以支持惰性求值,这意味着更改后不会立即重新计算该值,而下次请求该值时则会延迟进行计算。 All bindings and properties in this library support lazy evaluation. 该库中的所有绑定和属性都支持惰性评估。

An ObservableValue generates two types of events: change events and invalidation events. ObservableValue生成两种类型的事件:更改事件和无效事件。 A change event indicates that the value has changed. 更改事件表示该值已更改。 An invalidation event is generated if the current value is not valid anymore. 如果当前值不再有效,则会生成一个无效事件。 This distinction becomes important if the ObservableValue supports lazy evaluation, because for a lazily evaluated value one does not know if an invalid value really has changed until it is recomputed. 如果ObservableValue支持延迟求值,则这种区别就变得很重要,因为对于延迟求值的值,直到重新计算无效值,才知道该值是否真的发生了变化。 For this reason, generating change events requires eager evaluation while invalidation events can be generated for eager and lazy implementations. 因此,生成变更事件需要进行急切的评估,而无效事件可以针对急切和懒惰的实现生成。

Implementations of this class should strive to generate as few events as possible to avoid wasting too much time in event handlers. 此类的实现应努力生成尽可能少的事件,以避免在事件处理程序中浪费太多时间。 Implementations in this library mark themselves as invalid when the first invalidation event occurs. 当第一个失效事件发生时,该库中的实现将自己标记为无效。 They do not generate anymore invalidation events until their value is recomputed and valid again. 在重新计算其值并再次使其有效之前,它们不再生成无效事件。

Two types of listeners can be attached to an ObservableValue : InvalidationListener to listen to invalidation events and ChangeListener to listen to change events. 可以将两种类型的侦听器附加到ObservableValueInvalidationListener侦听无效事件和ChangeListener侦听变更事件。

Important note: attaching a ChangeListener enforces eager computation even if the implementation of the ObservableValue supports lazy evaluation. 重要说明:即使ObservableValue的实现支持延迟评估,附加ChangeListener也会强制进行急切的计算。

Note that both Property#bind and Bindings#createXXXBinding register an InvalidationListener on the dependency/dependencies, not a ChangeListener . 请注意, Property#bindBindings#createXXXBinding在依赖Bindings#createXXXBinding注册了InvalidationListener ,而不是ChangeListener

As you can see, bindings and properties in core JavaFX are lazy. 如您所见,核心JavaFX中的绑定和属性是惰性的。 You never query the value after you remove the element from the ObservableList so the value is never recomputed. ObservableList删除元素后,您再也不会查询值,因此永远不会重新计算该值。 Since the value is never recomputed, your Callable is not invoked for the second time. 由于永远不会重新计算该值,因此不会第二次调用您的Callable

I was actually surprised you saw "List has changed" even once. 我真的很惊讶您甚至看到"List has changed" None of your code requests the value so I wouldn't have expected the value to be computed. 您的代码都不要求该值,因此我不会期望要计算该值。 However, looking at the implementation, it looks like the act of registering an InvalidationListener causes the ObservableValue to be validated (ie the value is queried)—and #bind adds an InvalidationListener . 但是,从实现的角度看,注册InvalidationListener的行为似乎使ObservableValue受到验证(即,查询了该值),并且#bind添加了InvalidationListener I'm not sure why the implementation does this, but it does. 我不确定实现为什么这样做,但是确实如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM