1.首先什么是观察者模式?
通过现实中的一个例子说明:
杂志社(被观察者)———-读者(观察者)
读者通过订阅杂志社的期刊,杂志社每当有新的期刊发布都会邮寄给读者,读者便可以了解期刊的内容。杂志社有一份名单(即List集合),名单的成员是通过注册的方式添加的。新杂志一出来,杂志社就遍历名单,给每一个注册的读者邮寄一本杂志,而不需要读者经常关注杂志是否更新,节省了读者的精力,即节约了资源。
其实观察者模式就是这么简单的一个道理。
2.ListView中的应用
最常用的ListView如果数据源改变,经常会调用notifyDataSetChanged方法,先看源码。
public void notifyDataSetChanged() {
//看到observable就应该知道跟观察者模式沾边了,
mDataSetObservable.notifyChanged();
}
再看notifyChanged方法源码:mObservers是一个List观察者集合。即通过notifyDataSetChanged方法最终调用的观察者集合中每个观察者的onChaged方法。
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
看到这里好像差不多已经知道ListView刷新界面机制就是通过观察者模式,但是又没有十足的把握,不急,我们再看一下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);
}
有吃完全可以断定,就是应用的观察者模式。但是在每个观察者onchange方法里到底干了什么,我们还是不清楚。
接下来 看一下setAdapter的源码。
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
//从这里就可以看出来当setAdatpter的时候,首先做了一个解绑的动作,惯例操作
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
// AbsListView#setAdapter will update choice mode states.
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
//创建了一个观察者,查看AdapterDataSetObserver的源码
mDataSetObserver = new AdapterDataSetObserver();
//并且注册到被观察者中。
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();
}
查看AdapterDataSetObserver的源码:是在ListView的父类AbsListView中定义的
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();
}
}
}
这里调用的onChange方法里面,是在也看不出个所以然,是super.onchage();再找到它的父类AdapterView.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();
}
//省略
}
到此终于告一段落,找到了元凶,实现就在AdapterDataSetObserver中的onchange方法里,获取新的list数目,重新布局,从而实现刷新界面。
3.RxJava
RxJava是典型的观察者模式。
1.RxJava中的被观察者是Observable,观察者是Observer和Subscriber,Observer最终也会先成为Subscriber。
2.订阅关系,是被观察者把观察者放进名单
observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);
3.达成契约关系,Observable会依次发送队列中消息,调用观察者的一系列方法,如onNext,最后一个调用onComplete,发生错误则会调用onError,后两个方法还是互斥,只能调用一个。
4.同时,被观察者与观察者也是有注册,解除注册,判断是否注册等一系列方法来改变二者之间的契约关系。
5.不多介绍,是典型的观察者模式。