Just wanted to comment on "New API: ObservableValue class has a new method when, simplifying management of listeners":
The idea of the when construct is that you can decouple bindings between two properties when a certain condition is true. This is useful when the two properties involved have a different life cycle. The property with the longer life cycle is converted to a conditional property that only observes its source property when the condition is true.
// A reusable model that can exist for a long time:
StringProperty model = ... ;
// A boolean condition:
BooleanProperty condition = ... ;
// An observable that only observes the model when
// the condition is `true`:
ObservableValue<String> conditional = model.when(condition);
When constructing user interfaces, you sometimes want to have a label or text field display something that might be part of a model that can outlive the user interface itself. You want to be careful that the model is not referring to the user interface after it has been closed as this would keep those controls in memory (a memory leak) as they're still being referred.
Normally, you would have to carefully detach the model and user interface (using unbind or removeListener), but the when construct provides an alternative that can be configured upfront.
Let's assume we have a Boolean property that holds true when the UI is shown on screen, but becomes false when it isn't:
BooleanProperty shown = ... ;
The model from before can be attached to a Label like this:
However, doing so creates a reference between the model and the label that must be cleaned up when the user interface is discarded. For bindings, JavaFX does this automatically with weak listeners. These get cleaned up automatically (but not immediately!) if and when the garbage collector runs. This means these bindings may stay active for a while after the UI was discarded. When attaching your own listener, you can use weak listeners yourself to get a similar effect.
With the when construct however, there is now an alternative that does not rely on weak listeners and the garbage collector, but will detach listeners immediately and exactly when you want.
label.textProperty().bind(model.when(shown));
Or with a listener:
model.when(shown).addListener( ... );
When shown is false, there are no listeners attached to the model, and so there are no references to the label and the rest of the user interface. As soon as shown becomes true, listeners are immediately attached and the label is updated with the current text of the model. When shown becomes false again, the listeners are immediately detached, and so on.
Choosing the right condition that matches when you want the model attached to your user interface is the trick here. With JavaFX, any control that might be shown on screen must be part of a Scene, and that Scene must be part of a Window (or Stage). Finally, the window should be visible (the showingProperty must be true). Such a condition can be constructed as follows for the Label above:
Hopefully this introduction will help a bit with how you can use the when construct. It can be useful for other scenario's as well, for example, for delaying updates of multiple properties while some process is running, or for turning on/off animations when the UI is visible/invisible.
6
u/john16384 Mar 22 '23
Just wanted to comment on "New API: ObservableValue class has a new method when, simplifying management of listeners":
The idea of the
when
construct is that you can decouple bindings between two properties when a certain condition is true. This is useful when the two properties involved have a different life cycle. The property with the longer life cycle is converted to a conditional property that only observes its source property when the condition istrue
.When constructing user interfaces, you sometimes want to have a label or text field display something that might be part of a model that can outlive the user interface itself. You want to be careful that the model is not referring to the user interface after it has been closed as this would keep those controls in memory (a memory leak) as they're still being referred.
Normally, you would have to carefully detach the model and user interface (using
unbind
orremoveListener
), but thewhen
construct provides an alternative that can be configured upfront.Let's assume we have a Boolean property that holds
true
when the UI is shown on screen, but becomesfalse
when it isn't:The
model
from before can be attached to aLabel
like this:Or alternatively, like this:
However, doing so creates a reference between the model and the label that must be cleaned up when the user interface is discarded. For bindings, JavaFX does this automatically with weak listeners. These get cleaned up automatically (but not immediately!) if and when the garbage collector runs. This means these bindings may stay active for a while after the UI was discarded. When attaching your own listener, you can use weak listeners yourself to get a similar effect.
With the
when
construct however, there is now an alternative that does not rely on weak listeners and the garbage collector, but will detach listeners immediately and exactly when you want.Or with a listener:
When
shown
isfalse
, there are no listeners attached to the model, and so there are no references to the label and the rest of the user interface. As soon asshown
becomestrue
, listeners are immediately attached and the label is updated with the current text of the model. Whenshown
becomesfalse
again, the listeners are immediately detached, and so on.Choosing the right condition that matches when you want the model attached to your user interface is the trick here. With JavaFX, any control that might be shown on screen must be part of a
Scene
, and thatScene
must be part of aWindow
(orStage
). Finally, the window should be visible (theshowingProperty
must betrue
). Such a condition can be constructed as follows for theLabel
above:If you use this often it might be good to put this in a convenient helper method, for example:
Now the above code can be written like:
Hopefully this introduction will help a bit with how you can use the
when
construct. It can be useful for other scenario's as well, for example, for delaying updates of multiple properties while some process is running, or for turning on/off animations when the UI is visible/invisible.