java.util.Observable中有两个方法对Observer特别重要
①setChanged()方法
/**
*Setsthechangedflagforthis{@codeObservable}.Aftercalling
*{@codesetChanged()},{@codehasChanged()}willreturn{@codetrue}.
*/
protectedvoidsetChanged(){
changed=true;
}
②notifyObservers()方法 / notifyObservers(Object data)方法
/**
*If{@codehasChanged()}returns{@codetrue},callsthe{@codeupdate()}
*methodforeveryobserverinthelistofobserversusingnullasthe
*argument.Afterwards,calls{@codeclearChanged()}.
*
*Equivalenttocalling{@codenotifyObservers(null)}.
*/
publicvoidnotifyObservers(){
notifyObservers(null);
}
/**
*If{@codehasChanged()}returns{@codetrue},callsthe{@codeupdate()}
*methodforeveryObserverinthelistofobserversusingthespecified
*argument.Afterwardscalls{@codeclearChanged()}.
*
*@paramdata
*theargumentpassedto{@codeupdate()}.
*/
@SuppressWarnings("unchecked")
publicvoidnotifyObservers(Objectdata){
intsize=0;
Observer[]arrays=null;
synchronized(this){
if(hasChanged()){
clearChanged();
size=observers.size();
arrays=newObserver[size];
observers.toArray(arrays);
}
}
if(arrays!=null){
for(Observerobserver:arrays){
observer.update(this,data);
}
}
}
以上两个方法十分重要
setChanged()方法 ——
用来设置一个内部标志位注明数据发生了变化
notifyObservers()方法 / notifyObservers(Object data)方法 ——
通知所有的Observer数据发生了变化,这时所有的Observer会自动调用复写好的update(Observable observable, Object data)方法来做一些处理(比如说画面数据的更新)。
我们可以看到通知Observer有两个方法,一个无参,一个有参。那么这个参数有什么作用呢?
其中一个作用:现在我不想通知所有的Observer,而只想其中一个指定的Observer做一些处理,那么就可以传一个参数作为ID,然后在所有的Observer中判断,每个Observer判断只有接收到底参数ID是属于自己的才做一些处理。
当然参数还有其他作用,我只是举了个例子。
下面举个例子加以说明:
importjava.util.Observable;
/**
*被观察者类
*/
publicclassSimpleObservableextendsObservable
{
privateintdata=0;
publicintgetData(){
returndata;
}
publicvoidsetData(inti){
if(this.data!=i){
this.data=i;
setChanged();
//只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。
notifyObservers();
}
}
}
上面这个类是一个被观察者类,它继承了Observable类,表示这个类是可以被观察的。
然后在setData()方法里面,也就是数据改变的地方,来调用Observable类的setChanged()方法和notifyObservers()方法,表示数据已改变并通知所有的Observer调用它们的update()方法做一些处理。
注意:只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。
/**
*观察者类
*/
publicclassSimpleObserverimplementsObserver
{
publicSimpleObserver(SimpleObservablesimpleObservable){
simpleObservable.addObserver(this);
}
publicvoidupdate(Observableobservable,Objectdata){//data为任意对象,用于传递参数
System.out.println(“Datahaschangedto”+(SimpleObservable)observable.getData());
}
}
通过生成被观察者(SimpleObservable类)的实例,来调用addObserver(this)方法让观察者(SimpleObserver类)达到观察被观察者(SimpleObservable类)的目的。
然后还要复写update()方法,做数据改变后的一些处理。
下面可以写一个简单的测试类来测试一下
publicclassSimpleTest
{
publicstaticvoidmain(String[]args){
SimpleObservabledoc=newSimpleObservable();
SimpleObserverview=newSimpleObserver(doc);
doc.setData(1);
doc.setData(2);
doc.setData(2);
doc.setData(3);
}
}
运行结果如下
Datahaschangedto1
Datahaschangedto2//第二次setData(2)时由于没有setChange,所以update没被调用
Datahaschangedto3
下面介绍一个Observable类的其他一些属性和方法
属性 ——
//observers是一个List,保存着所有要通知的observer。
Listobservers=newArrayList();
//changed是一个boolean型标志位,标志着数据是否改变了。
booleanchanged=false;
方法 ——
//添加一个Observer到列表observers中
publicvoidaddObserver(Observerobserver){
if(observer==null){
thrownewNullPointerException();
}
synchronized(this){
if(!observers.contains(observer))
observers.add(observer);
}
}
//从列表observers中删除一个observer
publicsynchronizedvoiddeleteObserver(Observerobserver){
observers.remove(observer);
}
//清空列表observers
publicsynchronizedvoiddeleteObservers(){
observers.clear();
}
//返回列表observers中observer的个数
publicintcountObservers(){
returnobservers.size();
}
//重置数据改变标志位为未改变
protectedvoidclearChanged(){
changed=false;
}
//将数据改变标志位设置为改变
protectedvoidsetChanged(){
changed=true;
}
//判断标志位的值
publicbooleanhasChanged(){
returnchanged;
}
//通知所有observer(无参)
publicvoidnotifyObservers(){
notifyObservers(null);
}
//通知所有observer(有参)
@SuppressWarnings("unchecked")
publicvoidnotifyObservers(Objectdata){
intsize=0;
Observer[]arrays=null;
synchronized(this){
if(hasChanged()){
clearChanged();
size=observers.size();
arrays=newObserver[size];
observers.toArray(arrays);
}
}
if(arrays!=null){
for(Observerobserver:arrays){
observer.update(this,data);
}
}
}
注意:在Observer对象销毁前一定要用deleteObserver将其从列表中删除,也就是在onDestroy()方法中调用deleteObserver()方法。
不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误,而且随着列表越来越大,notifyObservers操作也会越来越慢。
下面2个工程是Observable与Observer的经典运用,是android实现的单指拖动放大图片的操作
两个例子: