Subject:抽象主题,也就是被观察者(Observable)
ConcreteSubject:具体主题
Observer:抽象观察者
ConcreteObserver:具体的观察者
观察者模式ListView与Adapter
ListView数据变化后,会调用Adapter的notifyDataSetChanged()方法,这个方法定义在BaseAdapter中
BaseAdapter.java
package android.widget;
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
这是一个观察者模式。被观察者DataSetObservable,那么观察者是什么呢。
DataSetObservable.java
package android.database;
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
// 调用所有观察者的onChanged方式
//注意这里从后往前遍历,是为了防止app在onChanged()方法实现里,
//把自己从mObservers集合里移除了,这时候正向遍历就会引起问题
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
}
代码就是调用mObservers的onChanged()方法,那么这些观察者从哪里来的?其实是ListView在setAdapter()的时候设置的。
ListView.java
package android.widget;
public class ListView extends AbsListView {
public void setAdapter(ListAdapter adapter) {
...
if (mAdapter != null) {
...
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
}
package android.widget;
public abstract class AbsListView {
private FastScroller mFastScroll;
private void setFastScrollerEnabledUiThread(boolean enabled) {
if (mFastScroll != null) {
mFastScroll.setEnabled(enabled);
} else if (enabled) {
mFastScroll = new FastScroller(this, mFastScrollStyle);
mFastScroll.setEnabled(true);
}
...
}
/**
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();
}
}
}
}
package android.widget;
public abstract class AdapterView<T extends Adapter> extends ViewGroup {
class AdapterDataSetObserver extends DataSetObserver {
@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的setAdapter()里给被观察者DataSetObservable注册观察者AbsListView.AdapterDataSetObserver,DataSetObservable放在BaseAdapter里引用,在数据发生变化时,调用adapter的notifyDataSetChanged()方法,而该方法其实是调用了DataSetObservable的notifyChanged()方法,最终会调用observer的onChanged()方法,也就是AdapterView.AdapterDataSetObserver实现的onChanged()方法,在这个方法里会调用对应ListView的requestLayout()去刷新布局。
ConcreteSubject:具体主题
Observer:抽象观察者
ConcreteObserver:具体的观察者
观察者模式ListView与Adapter
ListView数据变化后,会调用Adapter的notifyDataSetChanged()方法,这个方法定义在BaseAdapter中
BaseAdapter.java
package android.widget;
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
这是一个观察者模式。被观察者DataSetObservable,那么观察者是什么呢。
DataSetObservable.java
package android.database;
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
// 调用所有观察者的onChanged方式
//注意这里从后往前遍历,是为了防止app在onChanged()方法实现里,
//把自己从mObservers集合里移除了,这时候正向遍历就会引起问题
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
}
代码就是调用mObservers的onChanged()方法,那么这些观察者从哪里来的?其实是ListView在setAdapter()的时候设置的。
ListView.java
package android.widget;
public class ListView extends AbsListView {
public void setAdapter(ListAdapter adapter) {
...
if (mAdapter != null) {
...
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
}
package android.widget;
public abstract class AbsListView {
private FastScroller mFastScroll;
private void setFastScrollerEnabledUiThread(boolean enabled) {
if (mFastScroll != null) {
mFastScroll.setEnabled(enabled);
} else if (enabled) {
mFastScroll = new FastScroller(this, mFastScrollStyle);
mFastScroll.setEnabled(true);
}
...
}
/**
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();
}
}
}
}
package android.widget;
public abstract class AdapterView<T extends Adapter> extends ViewGroup {
class AdapterDataSetObserver extends DataSetObserver {
@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的setAdapter()里给被观察者DataSetObservable注册观察者AbsListView.AdapterDataSetObserver,DataSetObservable放在BaseAdapter里引用,在数据发生变化时,调用adapter的notifyDataSetChanged()方法,而该方法其实是调用了DataSetObservable的notifyChanged()方法,最终会调用observer的onChanged()方法,也就是AdapterView.AdapterDataSetObserver实现的onChanged()方法,在这个方法里会调用对应ListView的requestLayout()去刷新布局。