观察者模式
定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用场景
有一个事件发生改变,需要通知其他多个对象时.更多的应用于异步回调场景.
代码实现
UML类图结构
代码实践
1.Subject主题
public class Subject {
/**
* 事件持有观察者的集合
*/
private List<Observer> observers=new ArrayList<>();
/**
* 事件的状态
*/
private String state;
/**
* 增加观察者
*/
public void attach(Observer observer){
observers.add(observer);
}
/**
* 遍历通知观察者
*/
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update(state);
}
}
public String getState() {
return state;
}
/**
* 当状态发生改变,通知观察者
*/
public void setState(String state) {
this.state = state;
notifyAllObservers();
}
}
2.观察者接口
public interface Observer {
/**
* 更新观察者的状态
*/
public void update(String state);
}
3.观察者具体实现
public class Observer1 implements Observer {
@Override
public void update(String state) {
// TODO Auto-generated method stub
System.out.println("Observer1 update:"+state);
}
}
4.测试
public class Test {
public static void main(String[] args) {
//新建事件
Subject subject=new Subject();
//新建观察者
Observer observer1=new Observer1();
Observer observer2=new Observer2();
//绑定观察者
subject.attach(observer1);
subject.attach(observer2);
//更新事件状态
subject.setState("我更新了");
}
}
5.测试结果
Observer1 update:我更新了
Observer2 update:我更新了
ListView中的观察者模式
在adapter中有一个内部类AdapterDataSetObserver,这个就是一个观察者.
在listView.setadapter时候会初始观察者.
在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。
源码分析
BaseAdapter 中notifyDataSetChanged 调用的mDataSetObservable.notifyChanged();
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
// 数据集观察者,这里将观察者放到一个类中集中管理
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
* 当数据集用变化时通知所有观察者
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
在mDataSetObservable.notifyChanged()中遍历所有观察者,并且调用它们的onChanged方法。
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
*/
public void notifyChanged() {
synchronized(mObservers) {
// 调用所有观察者的onChanged方式
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
...
}
继承自AbsListView的父类AdapterView的AdapterDataSetObserver,
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
// 上文有说道,调用Adapter的notifyDataSetChanged的时候会调用所有观察者的onChanged方法,核心实现就在这里
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
// 获取Adapter中数据的数量
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
// 重新布局ListView、GridView等AdapterView组件
requestLayout();
}
...
public void clearSavedState() {
mInstanceState = null;
}
总结
所谓观察者模式,就是
多个观察者Observer
-->观察attach
--> 目标Subject
的变化--->并通知刷新update