引言
act 中有两个fragment,子fragment之间的通信,就会用到 观察者模式。
两个 activity 之间维护同一个数据源,如果要做到数据同步,就要用到观察者模式。
ListView 的数据跟新就会用到 观察者模式
概念
定义对象之间的一对多的依赖关系
每当一个对象状态发生改变时,其相关依赖对象皆得到通知,并被自动更新
使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面
- 一个对象的改变将导致一个或多个其他对象也发生改变
要是一对一的话 直接用接口的回掉就好了 - 需要在系统中创建一个出发链
A 影响 B ,B 影响 C
分析
被观察者,保存了 所有观察者引用的一个集合。
同时提供一个接口给我,用于增加删除 观察着对象
观察者收到通知,做自己的事情。
notify
Code
将观察者的引用集合 遍历执行 接口方法
调用JAVA 内置的接口 Observer
Observable 被观察者
Observe 观察者
主要是
this.setChanged();
this.notifyObservers(); 通知观察者
用的集合框架是 Vector 集合框架,为什么呢?是从线程安全的角度去考虑的
同时的删除 观察者,又通知/
是否有替代类?
因为 arraylist 非线程安全
CopyOnWriteArrayList . 是线程安全的
Android 中的应用
回调模式
Onclick()
一对一
BaseAdapter
listview 的 notifyDataChanged
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
看看这个类
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();
}
}
}
使用了倒序的遍历 为什呢? 避免观察者列表 删除的时候数据的同步问题
看看 BaseAdapter 中的注册
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
这就是观察者
看AbsListView的 setAdapter 往下走
AdapterView 有个内部类
class AdapterDataSetObserver extends DataSetObserver {
}
看代码
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()
网友评论