一、概述
观察者模式在Android中应用非常广泛,这篇文章就以这个模式的角度来看一看Google开发者是怎么在ListView的源码设计中运用这一模式的。先看一张图:
从上图中我们总结一个结论:ListView为观察者角色,BaseAdapter为被观察者角色,ListView通过setAdapter方法和BaseAdapter产生关联,对其进行监听,BaseAdapter中有观察者的集合,当adapter调用notifyDataSetChanged方法后,就会调用观察者的onChange方法,然后调用requestLayout方法,重新绘制界面。
带着结论,我们一起看看源码
二、源码分析
BaseAdapter持有观察者的集合
private final DataSetObservable mDataSetObservable = new DataSetObservable();
看一下DataSetObservable
public class DataSetObservable extends Observable {
/**
* Invokes {@link DataSetObserver#onChanged} on each observer.
* Called when the contents of the data set have changed. The recipient
* will obtain the new contents the next time it queries the data set.
*/
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
/**
* Invokes {@link DataSetObserver#onInvalidated} on each observer.
* Called when the data set is no longer valid and cannot be queried again,
* such as when the data set has been closed.
*/
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}
这个类继承自系统的Observable,看Observable中的代码:
protected final ArrayList mObservers = new ArrayList();
这个类,里面有mObservers 集合,用来装观察者,用泛型T表示这里就是DataSetObserver。
ListView作为观察者应该是持有DataSetObserver的 我们看关键源码
public void setAdapter(ListAdapter adapter) {
....省略....
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
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();
}
mDataSetObserver = new AdapterDataSetObserver()这句代码,就是在listView调用setAdapter之后就会把观察者mDataSetObserver 实例化出来,mDataSetObserver这个成员变量在其父类AbsListView中 看看代码
class AdapterDataSetObserver extends AdapterView.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
@Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
}
其继承自AdapterDataSetObserver而这个AdapterDataSetObserver继承自DataSetObserver 这样就是listView在setAdapter的时候 就实例化了观察者mDataSetObserver,对BaseAdapter数据改变进行监听。
而当listview数据改变时,用调用 notifyDataSetChanged方法,看源码
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
adapter中的观察者集合mDataSetObservable就会调用notifyChanged()方法
再看notifyChanged方法:
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
用for循环调用观察者的onChange方法,我们接着看onChanged()源码:
public abstract class DataSetObserver {
/**
* This method is called when the entire data set has changed,
* most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
*/
public void onChanged() {
// Do nothing
}
...省略...
}
空方法,我们看他的实现类,也就是上面看过的AdapterDataSetObserver
class AdapterDataSetObserver extends AdapterView.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
...省略...
}
}
这里调用了AbsListView的父类AdapterView的onChanged()方法 super.onChanged();
再看其具体代码:
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();
}
这里就会调用 requestLayout(); 方法开始listView的绘制,分析完毕,整个过程就是一个观察者模式很好的运用。