观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。该模式一个重要作用就是解耦,将被观察者和观察者进行解耦,使他们之间的依赖性更小
这里我们以微信公众号的订阅为例。公众号当其更新内容时就会推送给订阅了该公众号的读者。
//被观察者
public class Wechat extends Observable{
public void postNewPublication(String content){
setChanged();
notifyObservers(content);
}
}
//观察者
public class Reader implements Observer{
public String name ;
public Reader(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
Log.i(TAG, "update: wechat is update content is :"+arg);
}
}
public void test(){
Wechat wechat=new Wechat();
Reader reader1=new Reader("reader1");
Reader reader2=new Reader("reader2");
Reader reader3=new Reader("reader3");
wechat.addObserver(reader1);
wechat.addObserver(reader2);
wechat.addObserver(reader3);
wechat.postNewPublication("up up up");
}
这里需要注意的是Observer和Observable是JDK内置的类,表示观察者和被观察者。
当我们在使用ListView或RecycleView时如果数据发生变化我们会调用Adapter的notifyDataSetChanged()方法,如下所示
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
在方法内部调用了mDataSetObservable.notifyChanged,这里的mDataSetObservable是一个DataSetObservable实例
private final DataSetObservable mDataSetObservable = new DataSetObservable();
而DataSetObservable继承自Observable,我们看下DataSetObservable的notifyChanged方法
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
}
可以看到调用了DataSetObserver的onChanged方法,DataSetObserver是一个抽类这里mObservers.get(i)获得的是其子类AdapterDataSetObserver.
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
//重新布局
requestLayout();
}
...
public void clearSavedState() {
mInstanceState = null;
}
}
可以看到在AdapterDataSetObserver的onChanged方法中调用了requestLayout来进行重新布局。
在Android中广播也是基于观察者模式的
观察者模式优点:
缺点: