ListView 为了方便使用,自己在setAdapter()的时候就会register 一个新的AdapterDataSetObserver,以响应之后的adapter的notifyDataSetChanged(),本质就是一个观察者模式的实现:
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
..................................................
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
......................................................
}
BaseAdapter:
下面的操作全部委托给mDataSetObservable了:
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
而 private final DataSetObservable mDataSetObservable = new DataSetObservable();
DataSetObservable:
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();
}
}
}
挨个调用在自己这里注册的Observer的onChanged(),
那么对于ListView, 就一定会调用ListView自己register的AdapterDataSetObserver,
AdapterDataSetObserver定义在AbsListView中,是ListView的父类,
而 AdapterDataSetObserver extends AdapterView<ListAdapter>.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();
}
................................................................
}
可以看到,notifyDataSetChanged()最重要的是调用到了AdaperView(其实这里是ListView)的requestLayout,
这样就在这一次出发的layout()(onLayout())里,就可以更新要显示的数据和View了。
ListView是自己直接为自己register了一个DataSetObserver, 但是AdapterView自己是不会配的,用的话,要自己register一个,
这也符合子类(ListView)扩展父类(AdapterView)的方式.