观察者模式定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
Android 开发中一个比较典型的例子是点击监听器OnClickListener 。对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的OnClickListener 。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。当然,这也得益于我们可以随意定制自己程序中的观察者和被观察者。
观察者模式可以看作是一种通知机制,可以实现一处通知,多处改变。
public class Observable {
List<Observer> observers = new ArrayList<Observer>();//存储观察者的集合
boolean changed = false;
public Observable() {
}
//添加观察者
public void addObserver(Observer observer) {
if (observer == null) {
throw new NullPointerException("observer == null");
}
synchronized (this) {
if (!observers.contains(observer))
observers.add(observer);
}
}
protected void clearChanged() {
changed = false;
}
public int countObservers() {
return observers.size();
}
//删除观察者
public synchronized void deleteObserver(Observer observer) {
observers.remove(observer);
}
public synchronized void deleteObservers() {
observers.clear();
}
public boolean hasChanged() {
return changed;
}
public void notifyObservers() {
notifyObservers(null);
}
//通知观察者数据更新
@SuppressWarnings("unchecked")
public void notifyObservers(Object data) {
int size = 0;
Observer[] arrays = null;
synchronized (this) {
if (hasChanged()) {
clearChanged();
size = observers.size();
arrays = new Observer[size];
observers.toArray(arrays);
}
}
if (arrays != null) {
for (Observer observer : arrays) {
observer.update(this, data);
}
}
}
protected void setChanged() {
changed = true;
}
}
- 原理很简单,Observable中创建了一个List集合,用于存储观察者
- addObserver()添加观察者:往List集合中添加一个观察者对象
- deleteObserver()删除观察者:从List集合中删除一个观察者对象
- notifyObservers()更新数据:遍历List集合,调用观察者对象的update()方法,通知每一个观察者数据的更新
public interface Observer {
/**
* This method is called if the specified {@code Observable} object's
* {@code notifyObservers} method is called (because the {@code Observable}
* object has been updated.
*
* @param observable
* the {@link Observable} object.
* @param data
* the data passed to {@link Observable#notifyObservers(Object)}.
*/
void update(Observable observable, Object data);
}
Observer接口只有一个方法,就是通知数据更新的方法update()
通常情况下,我们不会使用系统提供的观察者模式,因为使用java api提供的观察者模式,必须去继承Observable,而由于java单继承的局限性,所以我们一般情况下都是自己去实现观察者模式。其实系统提供的观察者模式很简单,我们自己去实现的时候,只需要模仿着java api写就可以了。
public class Teacher {
public String message;
//发布消息
public void publishMessage(String message) {
this.message = message;
notifyObservers(message);
}
List<MyObserver> observers = new LinkedList<>();
//添加观察者
public void addObserver(MyObserver observer) {
if (observer == null) {
throw new NullPointerException("observer is null");
} else
synchronized (this) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
}
//删除观察者
public synchronized void deleteObserver(MyObserver observer) {
observers.remove(observer);
}
//通知观察者数据改变
public void notifyObservers(String message) {
for (MyObserver observer : observers) {
observer.update(message);
}
}
}
public interface MyObserver {
void update(String message);
}
public class Student implements MyObserver {
@Override
public void update(String message) {
System.out.println(getClass().getSimpleName()+"收到"+message);
}
}
public class Test {
public static void main(String[] args){
Teacher teacher = new Teacher();
Student student = new Student();
teacher.addObserver(student);
teacher.publishMessage("同学们,今天没有作业");
}
}
BaseAdapter
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();
}
}
DataSetObservable
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
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();
}
}
}
}
DataSetObserver
public abstract class DataSetObserver {
public void onChanged() {
}
public void onInvalidated() {
}
}
AdapterView
public abstract class AdapterView<T extends Adapter> extends ViewGroup {
class AdapterDataSetObserver extends DataSetObserver {
}
}
AbsListView
public abstract class AbsListView extends AdapterView<ListAdapter>{
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
}
}
在ListView的setAdapter()中添加观察者
public void setAdapter(ListAdapter adapter) {
// 如果已经有了一个Adapter,那么就先注销该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();
// 将这个观察者注册到Adapter中,实际上是注册到DataSetObservable
mAdapter.registerDataSetObserver(mDataSetObserver);
// 代码省略
} else {
// 代码省略
}
requestLayout();
}
当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged()方法,这个方法又会调用DataSetObservable的notifyChanged()方法,这个方法会调用所有观察者(AdapterDataSetObserver)的onChange()方法,在onChange()方法中又会调用ListView重新布局的方法requestLayout()使得ListView刷新界面。
- RxJava
- Data Binding
- EventBus
- Broadcast
- Loader
- ListView
- GridView
- RecyclerView
- Loader