转载请标明出处:
http://blog.csdn.net/hai_qing_xu_kong/article/details/76146635
本文出自:【顾林海的博客】
观察者模式也叫发布订阅模式,它是定义如下:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。适用的适用场景主要有关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系;事件多级触发场景;跨系统的消息交互场景,如消息队列、事件总线的处理机制。比如现在非常主流的EventBus, RxJava等框架就是采用的观察者模式。
观察者模式的通用类图如下:
Subject被观察者,定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
Observer观察者,观察者接受到消息后,即更新操作,对接收到的信息进行处理。
ConcreteSubject具体的被观察者,定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
ConcreteObserver具体的观察者,每个观察在接收到消息后的处理反应是不同,各个观察者自己的处理逻辑。
在日常中比如订阅新闻邮件就是一种典型的观察者模式,用户邮箱是观察者,新闻网站是被观察者,一旦新闻网站有新闻更新,会通知用户并给用户邮箱发送新闻。
创建新闻的实体类NewsBean:
/**
* 新闻实体类
*/
public class NewsBean {
public String title;
public String info;
}
创建观察者(Email)接口:
public interface EmailObserver {
void update(T news);
}
创建观察者(Email)具体实现类:
public class Email implements EmailObserver<NewsBean> {
private String user;
public Email(String user) {
this.user = user;
}
@Override
public void update(NewsBean news) {
System.out.println("尊敬的" + user + "用户,收到一封新闻邮件,标题为:" + news.title);
}
}
创建被观察者(新闻网站)抽象类:
public abstract class NewObservable {
private List observers = new ArrayList<>();
public void registerObserver(EmailObserver observer) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
public void unregisterObserver(EmailObserver observer) {
if (observers.contains(observer)) {
observers.remove(observer);
}
}
public void notifyObserver(T t) {
for (EmailObserver emailObserver : observers) {
emailObserver.update(t);
}
}
public void clearAllObserver() {
observers.clear();
}
}
NewObservable类中提供了观察者的添加、取消以及通知操作的实现。
创建被观察者(新闻网站)的具体实现:
public class NewService extends NewObservable<NewsBean> {
public void make() {
NewsBean newsBean = new NewsBean();
newsBean.title = "号外,号位,某某程序员居然找到女朋友了";
newsBean.info = "新闻内容.....";
notifyObserver(newsBean);
}
最后在场景类中使用:
public class Client {
public static final void main(String[] args) {
//创建被观察者新闻网站
NewService newService = new NewService();
//创建一些观察者用户
Email user1 = new Email("用户1");
Email user2 = new Email("用户2");
Email user3 = new Email("用户3");
//将观察者添加到被观察中
newService.registerObserver(user1);
newService.registerObserver(user2);
newService.registerObserver(user3);
//被观察者(网站)发布一则新闻
newService.make();
}
}
运行结果:
尊敬的用户1用户,收到一封新闻邮件,标题为:号外,号位,某某程序员居然找到女朋友了
尊敬的用户2用户,收到一封新闻邮件,标题为:号外,号位,某某程序员居然找到女朋友了
尊敬的用户3用户,收到一封新闻邮件,标题为:号外,号位,某某程序员居然找到女朋友了
在平时开发中,ListView用的比较多,可以通过setAdapter(adapter)方法给ListView设置适配器,其中的BaseAdapter就是实现了观察者模式。
BaseAdapter 源码:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
/*
数据集观察者
*/
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public boolean hasStableIds() {
return false;
}
/**
* 进行观察者的注册
*/
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
/**
* 该观察者的取消注册
*/
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* 通知观察者(ListView重绘当前可见区域)
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
/**
* 通知观察者(ListView会重绘控件)
*/
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
}
查看BaseAdapter会发现它就是一个观察者模式,其中的DataSetObservable是一个数据集的观察者,并且在BaseAdapter源码中实现了被观察者职责方法:动态地增加、取消观察者,管理观察者并通知观察者。其中notifyDataSetChanged()方法是用于通知ListView重绘当前的可见区域,notifyDataSetInvalidated()方法用于通知ListView重绘控件。
DataSetObservable承载这被观察者的职责,查看DataSetObservable源码:
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* 同步操作,通知观察者(这里是ListView)
*/
public void notifyChanged() {
synchronized(mObservers) {
/**
* 遍历观察者,并通知
*/
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
/**
* 同步操作,通知观察者(这里是ListView)
*/
public void notifyInvalidated() {
synchronized (mObservers) {
/**
* 遍历观察者,并通知
*/
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}
DataSetObservable内部实现了通知观察者(ListView)的方法,并继承自Observable泛型类,我们继续看Observable的源码,其实到这里大家应该能知道Observable类具体做了哪些操作,一定提供了对观察者的注册和取消注册操作,这里继承Observable泛型类时指定了具体的观察者类型是DataSetObserver,这里先提下DataSetObserver 这个观察者是在ListView某个父类中定义,其实也就很好的说明了ListView是观察者,观察实现了BaseAdapter类中的数据变化,一旦数据产生变化,通过BaseAdapter的notifyChanged()方法通知ListView的重绘。
Observable源码:
public abstract class Observable<T> {
/**
* 用于保存观察者的列表
*/
protected final ArrayList mObservers = new ArrayList();
/**
* 添加注册一个观察者到观察者列表中。
*/
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
/**
* 从列表中移除(取消注册)观察者。
*/
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
/**
* 情况所有观察者
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
Observable内部提供了一个用于保存观察者的列表,并提供了registerObserver(observer)方法用于注册观察到列表中,unregisterObserver(observer)方法用于从观察者列表移除一个观察者,以及unregisterAll()方法清空所有观察者。
到这里整个被观察者(BaseAdatper)已经分析完毕,这里总结一些知识点:
在给ListView添加适配器时,会调用ListView的setAdapter(adapter)方法,接下来从ListView的setAdater(adapter)方法的具体实现进行深入:
@Override
public void setAdapter(ListAdapter adapter) {
/**
* (1)第一次为ListView设置适配器时,如果已经存在观察者,就将它移除。
*/
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
/**
* (2)创建观察者。
*/
mDataSetObserver = new AdapterDataSetObserver();
/**
* (3)将观察者注册到被观察者中。
*/
mAdapter.registerDataSetObserver(mDataSetObserver);
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
int position;
if (mStackFromBottom) {
position = lookForSelectablePosition(mItemCount - 1, false);
} else {
position = lookForSelectablePosition(0, true);
}
setSelectedPositionInt(position);
setNextSelectedPositionInt(position);
if (mItemCount == 0) {
// Nothing selected
checkSelectionChanged();
}
} else {
mAreAllItemsSelectable = true;
checkFocus();
// Nothing selected
checkSelectionChanged();
}
requestLayout();
}
在setAdapter一开始就会去判断观察者是否存在,如果已经存在就会取消注册,在(2)中,会创建观察者,并在(3)中添加到被观察者中,AdapterDataSetObserver定义在ListView父类中。
AbsListView内部类AdapterDataSetObserver:
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
@Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
}
回到BaseAdapter中,在调用BaseAdapter的notifyChanged方法时会执行继承自Observable 泛型类的DataSetObservable中的notifyChanged()方法,在这个方法中去遍历父类中的观察者列表,并调用它们的onChanged()和onInvalidated()方法,在上面分析被观察者(BaseAdapter)时,已经知道了观察者的实例类是DataSetObserver,而AbsListView内部类AdapterDataSetObserver继承自 AdapterView内部类AdapterDataSetObserver。
AdapterView内部类AdapterDataSetObserver:
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
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();
requestLayout();
}
@Override
public void onInvalidated() {
mDataChanged = true;
if (AdapterView.this.getAdapter().hasStableIds()) {
// Remember the current state for the case where our hosting activity is being
// stopped and later restarted
mInstanceState = AdapterView.this.onSaveInstanceState();
}
// Data is invalid so we should reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mSelectedPosition = INVALID_POSITION;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
checkFocus();
requestLayout();
}
public void clearSavedState() {
mInstanceState = null;
}
}
由于AbsListView内部类AdapterDataSetObserver重写了 AdapterView内部类AdapterDataSetObserver的onChanged()和onInvalidated()方法 。也就是说BaseAdapter的notifyChanged最终执行到ListView的父类AbsListView的内部类AdapterDataSetObserver中的onChanged()和onInvalidated()方法,查看这两个方法可以看出它们调用了父类的onChanged()和onInvalidated()方法,可以看出ListView重绘的具体实现是在AdapterView内部类AdapterDataSetObserver类中实现的,在onChanged()和onInvalidated()方法中最终调用requestLayout()方法进行ListView、GridView等AdapterView组件的重新布局。
到这里整个观察者(ListView)已经分析完毕,这里总结一些知识点: