对象无效监听器
public interface InvalidationListener {
public void invalidated(Observable observable);
}
什么是对象无效?
被观察对象正在发生改变,或绑定了其他对象
可观察对象 Observable
public interface Observable {
void addListener(InvalidationListener listener);
void removeListener(InvalidationListener listener);
}
addListener方法添加一个当对象无效时的监听器。
removeListener方法则为移除一个监听器。
可观察对象改变监听器 ChangeListener
public interface ChangeListener<T> {
void changed(ObservableValue<? extends T> observable, T oldValue, T newValue);
}
当对象改变完成后,向所有监听器发出消息。
可观测值对象 ObservableValue
public interface ObservableValue<T> extends Observable {
void addListener(ChangeListener<? super T> listener);
void removeListener(ChangeListener<? super T> listener);
T getValue();
}
addListener方法添加一个当对象改变的监听器。
removeListener方法则为移除一个监听器
ObservableValue的值可以通过getValue获取。
文档中有说明:
ObservableValue生成两种类型的事件:改变事件和失效事件。更改事件表示值已更改。如果当前值不再有效,将生成一个无效事件。如果ObservableValue支持延迟计算,那么这种区别就变得很重要,因为对于延迟计算的值,在重新计算之前,人们不知道无效值是否真的发生了更改。因此,生成变更事件需要预先评估,而对于预先和延迟的实现可以生成失效事件。
此类的实现应该尽量少生成事件,以避免在事件处理程序中浪费太多时间。当第一个无效化事件发生时,此库中的实现将自己标记为无效。在重新计算值并再次有效之前,它们不会再生成失效事件。
当然这是一个函数式接口,但不建议直接使用。
监听器的存储
实现ObservableValue的方法
@Override
public void addListener(InvalidationListener listener) {
helper = ExpressionHelper.addListener(helper, this, listener);
}
@Override
public void removeListener(InvalidationListener listener) {
helper = ExpressionHelper.removeListener(helper, listener);
}
@Override
public void addListener(ChangeListener<? super Number> listener) {
helper = ExpressionHelper.addListener(helper, this, listener);
}
@Override
public void removeListener(ChangeListener<? super Number> listener) {
helper = ExpressionHelper.removeListener(helper, listener);
}
ExpressionHelper 有4个静态方法,用于管理可观察对象与监听器。
public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, InvalidationListener listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
observable.getValue(); // validate observable
return (helper == null)? new SingleInvalidation<T>(observable, listener) : helper.addListener(listener);
}
public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, InvalidationListener listener) {
if (listener == null) {
throw new NullPointerException();
}
return (helper == null)? null : helper.removeListener(listener);
}
public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, ChangeListener<? super T> listener) {
if ((observable == null) || (listener == null)) {
throw new NullPointerException();
}
return (helper == null)? new SingleChange<T>(observable, listener) : helper.addListener(listener);
}
public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, ChangeListener<? super T> listener) {
if (listener == null) {
throw new NullPointerException();
}
return (helper == null)? null : helper.removeListener(listener);
}
public static <T> void fireValueChangedEvent(ExpressionHelper<T> helper) {
if (helper != null) {
helper.fireValueChangedEvent();
}
}
只读属性 ReadOnlyProperty
public interface ReadOnlyProperty<T> extends ObservableValue<T> {
Object getBean();
String getName();
}
定义所有可读属性通用方法的通用接口。
对象实现此接口,那它将是可读的,即能get到该属性本身。
可写值对象接口 WritableValue
public interface WritableValue<T> {
T getValue();
void setValue(T value);
}
WritableValue是一个包含可读取和设置的值的接口
属性接口 Property
public interface Property<T> extends ReadOnlyProperty<T>, WritableValue<T> {
void bind(ObservableValue<? extends T> observable);
void unbind();
boolean isBound();
void bindBidirectional(Property<T> other);
void unbindBidirectional(Property<T> other);
}
bind 为此属性创建单向绑定。
unbind 删除此属性的单向绑定。
isBound 可以用于检查是否绑定了属性。
bindBidirectional 在这个属性和另一个属性之间创建双向绑定。双向绑定独立于单向绑定存在。因此,可以向具有双向绑定的属性添加单向绑定,反之亦然。然而,这种做法是不可取的。一个属性可以有多个双向绑定。
unbindBidirectional 删除此属性与另一个属性之间的双向绑定
可观察属性对象
以SimpleIntegerProperty为例
可写数值类型接口
public interface WritableNumberValue extends WritableValue<Number> {
}
WritableValue为可写值对象接口,类型指定Number
意味着WritableNumberValue为可写数值类型接口
可写整型值类型接口
WritableIntegerValue 指明了方法类型为int
public interface WritableIntegerValue extends WritableNumberValue {
int get();
void set(int value);
void setValue(Number value);
}
只读整型属性抽象类
ReadOnlyIntegerProperty 继承ReadOnlyProperty 将具有读取属性
IntegerExpression 定义了一些基本方法,比如用于绑定的方法。
public abstract class ReadOnlyIntegerProperty extends IntegerExpression
implements ReadOnlyProperty<Number> {
...
}
整型属性抽象类
此类定义了一个整型属性具有的读写操作和绑定操作。
public abstract class IntegerProperty extends ReadOnlyIntegerProperty implements
Property<Number>, WritableIntegerValue {
...
}
整型属性基类
public abstract class IntegerPropertyBase extends IntegerProperty {...}
在IntegerPropertyBase 中实现了 ObservableValue 的 5个方法
简单整型属性类
public class SimpleIntegerProperty extends IntegerPropertyBase {
private static final Object DEFAULT_BEAN = null;
private static final String DEFAULT_NAME = "";
private final Object bean;
private final String name;
public Object getBean() {
return bean;
}
public String getName() {
return name;
}
public SimpleIntegerProperty() {
this(DEFAULT_BEAN, DEFAULT_NAME);
}
public SimpleIntegerProperty(int initialValue) {
this(DEFAULT_BEAN, DEFAULT_NAME, initialValue);
}
public SimpleIntegerProperty(Object bean, String name) {
this.bean = bean;
this.name = (name == null) ? DEFAULT_NAME : name;
}
public SimpleIntegerProperty(Object bean, String name, int initialValue) {
super(initialValue);
this.bean = bean;
this.name = (name == null) ? DEFAULT_NAME : name;
}
}
getBean和getName为实现ReadOnlyProperty接口的方法
其余都是构造方法,都是围绕着bean,name,value属性
bean为一个对象,可以为空
name为SimpleIntegerProperty的名字,默认为DEFAULT_NAME。
name为SimpleIntegerProperty的值,默认为0。
测试
public static void main(String[] args) {
SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
System.out.println(a);
}
输出 :
IntegerProperty [name: a, value: 2]
添加监听器
public static void main(String[] args) {
SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
System.out.println(a);
a.addListener(new InvalidationListener() {
public void invalidated(Observable o) {
System.out.println("绑定现在无效");
}
});
a.addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("observable: "+observable);
System.out.println("oldValue :"+oldValue);
System.out.println("newValue :"+newValue);
}
});
a.set(3);
System.out.println(a);
输出 :
IntegerProperty [name: a, value: 2]
绑定现在无效
observable: IntegerProperty [name: a, value: 3]
oldValue :2
newValue :3
IntegerProperty [name: a, value: 3]
set方法调用了markInvalid()发出消息。
单向绑定
a 绑定b后,若改变a的值将导致异常。
public static void main(String[] args) throws InterruptedException {
SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
System.out.println(a);
SimpleIntegerProperty b=new SimpleIntegerProperty(null,"b",1);
System.out.println(b);
a.addListener(new InvalidationListener() {
public void invalidated(Observable o) {
System.out.println("绑定现在无效");
}
});
a.addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("observable: "+observable);
System.out.println("oldValue :"+oldValue);
System.out.println("newValue :"+newValue);
}
});
a.bind(b);
System.out.println(a);
b.set(3);
System.out.println(b);
System.out.println(a);
}
输出 :
IntegerProperty [name: a, value: 2]
IntegerProperty [name: b, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, bound, value: 1]
oldValue :2
newValue :1
IntegerProperty [name: a, bound, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, bound, value: 3]
oldValue :1
newValue :3
IntegerProperty [name: b, value: 3]
IntegerProperty [name: a, bound, value: 3]
解除单向绑定
方法unbind()
双向绑定
public static void main(String[] args) throws InterruptedException {
SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
System.out.println(a);
SimpleIntegerProperty b=new SimpleIntegerProperty(null,"b",1);
System.out.println(b);
a.addListener(new InvalidationListener() {
public void invalidated(Observable o) {
System.out.println("绑定现在无效");
}
});
a.addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.println("observable: "+observable);
System.out.println("oldValue :"+oldValue);
System.out.println("newValue :"+newValue);
}
});
a.bindBidirectional(b);
System.out.println(a);
a.set(3);
System.out.println(a);
System.out.println(b);
b.set(5);
System.out.println(a);
System.out.println(b);
}
输出 :
IntegerProperty [name: a, value: 2]
IntegerProperty [name: b, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, value: 1]
oldValue :2
newValue :1
IntegerProperty [name: a, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, value: 3]
oldValue :1
newValue :3
IntegerProperty [name: a, value: 3]
IntegerProperty [name: b, value: 3]
绑定现在无效
observable: IntegerProperty [name: a, value: 5]
oldValue :3
newValue :5
IntegerProperty [name: a, value: 5]
IntegerProperty [name: b, value: 5]
解除双向绑定
方法 unbindBidirectional(other)