我有一个用例,其中我想将多个ObservableValue绑定到一个Observable上,因为我实际上并不感兴趣,值更改是什么,我只需要一种方法在它更改时得到通知。
所以这是可以观察到的约束,我想到:
BooleanBinding() {
{
super.bind(proxy.activeShipProperty());
INavigableVessel activeShip = proxy.getActiveShip();
super.bind(activeShip.getLoadBinding());
if (activeShip instanceof IShip) {
super.bind(((IShip) activeShip).travelState());
} else {
super.bind(((IConvoy) activeShip).getOrlegShip().travelState());
}
super.bind(date.dayDateBinding());
}
private boolean value = true;
@Override
protected boolean computeValue() {
value = !value;
return value;
}
};然后,为了验证它是否正常工作,这个测试代码:
Observable observable = contentProvider.createObservable(ENoticeBoardType.SHIP_WARE_INFO, proxy);
IntegerProperty invalidationCounter = new SimpleIntegerProperty(0);
InvalidationListener listener = observable1 -> invalidationCounter.setValue(invalidationCounter.get() + 1);
observable.addListener(listener);
// When
dayBinding.invalidate();
loadBinding.invalidate();
travelState.set(EShipTravelState.ANCHOR);
activeVessel.set(mock(IShip.class));
// Then
assertEquals(4, invalidationCounter.get());但事实证明并非如此。invalidationCounter在第一次无效调用时只增加一次。
但是,当我将上面的BooleanBinding作为ObservableValue处理时,我可以添加一个ChangeListener:
ChangeListener listener = (obs, oldValue, newValue) -> invalidationCounter.setValue(invalidationCounter.get() + 1);
observable.addListener(listener);
// When
dayBinding.invalidate();
loadBinding.invalidate();
travelState.set(EShipTravelState.ANCHOR);
activeVessel.set(mock(IShip.class));
// Then
assertEquals(4, invalidationCounter.get());这如预期的那样起作用。
我想知道/已经确认的是: InvalidationListener只被调用一次,当Observable变得无效时,它就不会更改为有效,这样它就可以再次生效。但是,对于ChangeListener,必须计算新值,因此ObservableValue再次生效。
基于这一观察,是否有实际可以使用Observable的用例?
发布于 2018-07-21 07:38:46
Observable只是一个接口,实现决定是否调用invalidate会触发处于某种状态的侦听器。您在这里观察到的行为是BooleanBinding只触发一个invalidation更新,直到使用get()方法检索值为止。
期望观察者知道,一旦通知了侦听器,该值可能会发生变化。
这是一种优化,以避免不必要的计算。例如,考虑以下场景:有三个BooleanProperty的b1、b2和b3,您对b1 && (b2 || b3)感兴趣。在这种情况下,您可以应用短路评估,这不要求您评估(b2 || b3),如果b1是false,而评估(b2 || b3)不要求您评估b3,如果b2是true。如果b2和/或b3计算成本很高,那么如果可以避免计算它们,就会使代码更具性能,例如使用以下实现
BooleanBinding binding = new BooleanBinding() {
{
bind(b1, b2, b3);
}
@Override
protected boolean computeValue() {
if (!b1.get()) {
return false;
}
if (b2.get()) {
return true;
} else {
return b3.get();
}
// the above is basically a longer version of
// return b1.get() && (b2.get() || b3.get());
// to highlight the short circuiting behaviour
}
};与ChangeListener相反,InvalidationListener要求将新的值传递给它们,因此添加任何ChangeListener结果就会调用get(),并且每个invalidation调用都会触发computeValue调用。
https://stackoverflow.com/questions/51453064
复制相似问题