首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >InvalidationListener对ChangeListener

InvalidationListener对ChangeListener
EN

Stack Overflow用户
提问于 2018-07-21 05:21:22
回答 1查看 626关注 0票数 2

我有一个用例,其中我想将多个ObservableValue绑定到一个Observable上,因为我实际上并不感兴趣,值更改是什么,我只需要一种方法在它更改时得到通知。

所以这是可以观察到的约束,我想到:

代码语言:javascript
复制
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;
    }
};

然后,为了验证它是否正常工作,这个测试代码:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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的用例?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-21 07:38:46

Observable只是一个接口,实现决定是否调用invalidate会触发处于某种状态的侦听器。您在这里观察到的行为是BooleanBinding只触发一个invalidation更新,直到使用get()方法检索值为止。

期望观察者知道,一旦通知了侦听器,该值可能会发生变化。

这是一种优化,以避免不必要的计算。例如,考虑以下场景:有三个BooleanPropertyb1b2b3,您对b1 && (b2 || b3)感兴趣。在这种情况下,您可以应用短路评估,这不要求您评估(b2 || b3),如果b1false,而评估(b2 || b3)不要求您评估b3,如果b2true。如果b2和/或b3计算成本很高,那么如果可以避免计算它们,就会使代码更具性能,例如使用以下实现

代码语言:javascript
复制
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调用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51453064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档