我有以下代码:
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);
我不明白为什么这段代码只显示一次“列表已更改”?它应该两次,一次在绑定中,然后在删除中,因为该列表是可观察的。为什么列表更改不影响boolean属性?
(我在长代码中遇到了更大的问题,但是这种情况说明了我对布尔型属性绑定的误解)
谢谢!
答案 0 :(得分:2)
从ObservableValue
的{{3}}(Binding
和Property
都继承):
ObservableValue
的实现可能支持惰性求值,这意味着在更改后不会立即重新计算该值,而在下次请求该值时会延迟进行计算。该库中的所有绑定和属性都支持惰性评估。
ObservableValue
生成两种类型的事件:更改事件和无效事件。更改事件表示该值已更改。如果当前值不再有效,则会生成一个无效事件。如果ObservableValue
支持惰性求值,这一区别就变得很重要,因为对于惰性求值而言,直到重新计算无效值,才知道它是否真的已经改变。因此,生成变更事件需要进行急切的评估,而对于急切和懒惰的实现可以生成无效事件。此类的实现应努力生成尽可能少的事件,以避免在事件处理程序中浪费太多时间。当第一个失效事件发生时,该库中的实现将自己标记为无效。在重新计算其值并再次使其有效之前,它们不再生成无效事件。
ObservableValue
可以附加两种类型的侦听器:InvalidationListener
侦听无效事件,ChangeListener
侦听变更事件。重要说明:即使
ChangeListener
的实现支持惰性求值,附加ObservableValue
也会强制执行急切的计算。
请注意,Property#bind
和Bindings#createXXXBinding
都在相关性上注册了InvalidationListener
,而不是ChangeListener
。
如您所见,核心JavaFX中的绑定和属性是惰性的。从ObservableList
中删除元素后,您再也不会查询该值,因此永远不会重新计算该值。由于永远不会重新计算该值,因此不会再次调用您的Callable
。
我真的很惊讶您竟然看到"List has changed"
。您的代码都不要求该值,因此我不会期望要计算该值。但是,从实现的角度来看,注册InvalidationListener
的行为使ObservableValue
得到验证(即查询值),并且{{1} }添加一个#bind
。我不确定实现为什么要这样做,但是确实可以。