When we add a listener to an Parent
object in JavaFx (for example a TextField
), what are we really doing under the hood? Are we creating a thread that is observing that particular TextField
and when something change, the action by the thread take place?
I get confussed because every single thread program is working in sequence, so how it is possible to watch some variables whenever they change - I assume that something must perform concurrently (?).
Your assumptions are not correct: there is no threading involved in adding listeners to properties.
JavaFX properties are basically an implementation of the Observer pattern. The implementation used is quite complex, because these properties support "lazy evaluation", meaning that other objects can be notified that the current value is no longer valid, but without recalculating the value unless its requested.
However the basic idea is very simple: the property just keeps a list of listeners and notifies them if the set
method is called. The following code is not how StringProperty
is implemented in the library, but it will give you an idea what is happening:
public class ExampleStringProperty {
private final List<ChangeListener<? super String>> changeListeners
= new ArrayList<>();
private String value ;
public String get() {
return value ;
}
public void set(String value) {
if (! Objects.equals(value, this.value)) {
String oldValue = this.value ;
this.value = value ;
for (ChangeListener<? super String> listener : changeListeners) {
listener.changed(this, oldValue, value);
}
}
}
public void addListener(ChangeListener<? super String> listener) {
changeListeners.add(listener);
}
public void removeListener(ChangeListener<? super String> listener) {
changeListeners.remove(listener);
}
}
As you can see, no threading is involved: if the property is set, the listeners' changed(...)
methods are called on the same thread.
Here's a quick test, using the actual SimpleStringProperty
from the library:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class StringPropertyTest {
public static void main(String[] args) {
StringProperty prop = new SimpleStringProperty();
prop.addListener((obs, oldValue, newValue) -> {
System.out.printf("Property changed from %s to %s on thread %s%n",
oldValue, newValue, Thread.currentThread());
});
System.out.println("Running on thread "+Thread.currentThread());
System.out.println("Setting property to \"value\"");
prop.set("value");
System.out.println("Setting property to \"new value\" on thread "+Thread.currentThread());
prop.set("new value");
}
}
which produces the output
Running on thread Thread[main,5,main]
Setting property to "value"
Property changed from null to value on thread Thread[main,5,main]
Setting property to "new value" on thread Thread[main,5,main]
Property changed from value to new value on thread Thread[main,5,main]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With