第二期项目结束,继续自己的博客生涯。上周六给自己立过一个flag,对自己的承诺一定兑现,我就是注定成为大牛的偶豆扣。
Android开发中肯定少不了ListView,它总是配合BaseAdapter一起。每次我们更新数据的时候就会调用baseAdapter.notifyDataSetChanged()方法。实际其中就是用到了观察者模式。那今天我们就来看看ListView中是如何使用观察者模式的。
让我们先看看BaseAdapter的源码,不重要的代码忽略。但是其中有个hasStableIds()方法默认返回false,后面要用到。
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();
}
//通知所有观察者数据更替
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
BaseAdapter里有一个被观察者DataSetObservable实例,他继承自Observable,让我们来看看它们怎么写的
public abstract class Observable<T> {
/**
* 一个泛型T的观察者集合,
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* 添加观察者到集合
*/
public void registerObserver(T observer) {
synchronized(mObservers) {//对象同步锁
mObservers.add(observer);
}
}
/**
* 移除观察者
*/
public void unregisterObserver(T observer) {
synchronized(mObservers) {
mObservers.remove(index);
}
}
/**
* 移除所有观察者
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* 通知所有观察者数据改变
*/
public void notifyChanged() {
synchronized(mObservers) {//mObservers继承自Observable<T>
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
/**
* 通知所有观察者数据更替
*/
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}
典型的被观察者的写法,其实就是用一个集合来存储观察者,然后对这个集合进行操作。
listView.setAdapter(baseAdapter);//给listview设置适配器
接下来我们看看setAdapter的方法到底干了什么
@Override
public void setAdapter(ListAdapter adapter) {
//对观察者模式不重要的代码省略...
if (mAdapter != null) {
...
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
...
} else {...}
requestLayout();//重新布局
}
还记得BaseAdapter中的registerDataSetObserver方法吗?接下来看看AdapterDataSetObserver这个观察者是怎么写的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这个类只是单纯的设置了一下ListView的快速滚动,那我们去他的父类看看。它是AdapterView的一个内部类。
class AdapterDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
mDataChanged = true;//改变状态
mOldItemCount = mItemCount;//记录下上次的数量
mItemCount = getAdapter().getCount();//记录下这次的数量
//还记得hasStableIds默认返回什么吗?
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
....
} else {
rememberSyncState();//记住各种状态和数据(顶部偏移量等)
}
checkFocus();//检测焦点
requestLayout();//view的方法,重新布局
}
@Override
public void onInvalidated() {
...//重置了所有的位置状态
}
}
源码就看到这里,基本上逻辑已经搞清楚了。setAdapter的时候会注册一个观察者。notifyDataSetChanged的时候会通知观测者,可以让AdapterView调用相应的逻辑,最后刷新数据。