一赔癌、概述
觀察者模式在Android中應(yīng)用非常廣泛,這篇文章就以這個(gè)模式的角度來(lái)看一看Google開(kāi)發(fā)者是怎么在ListView的源碼設(shè)計(jì)中運(yùn)用這一模式的。先看一張圖:
從上圖中我們總結(jié)一個(gè)結(jié)論:ListView為觀察者角色,BaseAdapter為被觀察者角色,ListView通過(guò)setAdapter方法和BaseAdapter產(chǎn)生關(guān)聯(lián)宵膨,對(duì)其進(jìn)行監(jiān)聽(tīng),BaseAdapter中有觀察者的集合炸宵,當(dāng)adapter調(diào)用notifyDataSetChanged方法后辟躏,就會(huì)調(diào)用觀察者的onChange方法,然后調(diào)用requestLayout方法土全,重新繪制界面捎琐。
帶著結(jié)論,我們一起看看源碼
二裹匙、源碼分析
BaseAdapter持有觀察者的集合
private final DataSetObservable mDataSetObservable = new DataSetObservable();
看一下DataSetObservable
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* 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();
}
}
}
}
這個(gè)類(lèi)繼承自系統(tǒng)的Observable瑞凑,看Observable中的代碼:
protected final ArrayList<T> mObservers = new ArrayList<T>();
這個(gè)類(lèi),里面有mObservers 集合概页,用來(lái)裝觀察者籽御,用泛型T表示這里就是DataSetObserver。
ListView作為觀察者應(yīng)該是持有DataSetObserver的 我們看關(guān)鍵源碼
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調(diào)用setAdapter之后就會(huì)把觀察者mDataSetObserver 實(shí)例化出來(lái)技掏,mDataSetObserver這個(gè)成員變量在其父類(lèi)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();
}
}
}
其繼承自AdapterDataSetObserver而這個(gè)AdapterDataSetObserver繼承自DataSetObserver 這樣就是listView在setAdapter的時(shí)候 就實(shí)例化了觀察者mDataSetObserver,對(duì)BaseAdapter數(shù)據(jù)改變進(jìn)行監(jiān)聽(tīng)徽曲。
而當(dāng)listview數(shù)據(jù)改變時(shí)零截,用調(diào)用 notifyDataSetChanged方法,看源碼
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
adapter中的觀察者集合mDataSetObservable就會(huì)調(diào)用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循環(huán)調(diào)用觀察者的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
}
...省略...
}
空方法秃臣,我們看他的實(shí)現(xiàn)類(lèi)涧衙,也就是上面看過(guò)的AdapterDataSetObserver
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
...省略...
}
}
這里調(diào)用了AbsListView的父類(lèi)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();
}
這里就會(huì)調(diào)用 requestLayout(); 方法開(kāi)始listView的繪制,分析完畢奥此,整個(gè)過(guò)程就是一個(gè)觀察者模式很好的運(yùn)用弧哎。