自定义滚轮系列---设计模式之观察者模式

对于Adapter我相信大家都很熟悉,在使用ListView或者是GridView控件时,我们经常会用到Adapter,我们通常的做法是自定义一个Adapter继承自BaseAdapter,然后调用ListView的setAdapter()方法,将数据与ListView绑定起来。但是我们对于Adapter又了解多少呢,我们是否知道它的实现原理呢。

今天我们要说的是Adapter中的观察者模式,如果你想详细了解观察者模式,你可以参考这篇文章 设计模式学习笔记-观察者模式

一、关于观察者模式主要有以下几点:

1、定义:观察者模式(Observer Pattern)也叫发布订阅模式(Publish/subscribe),它是一个在项目中经常使用的模式,其定义如下:

Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖与他的对象都会得到通知并被自动更新)

2、观察者模式的通用类图:

3、观察者模式的几个角色名称:

·Subject被观察者:定义被观察者必须实现的职责,他必须能够动态的增加,取消观察者。他一般是抽象类或者实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知被观察者。

·Observer被观察者:观察者接受到消息之后,即进行update(更新方法)操作,对接收到的信息进行处理。

·ConcreteSubject具体的被观察者:定义被观察者自己业务逻辑,同时定义对哪些事件进行通知。

·ConcreteObserver具体的观察者:每个观察者的在接收到消息后的处理反应是不同的,各个反应者有自己的处理逻辑。

 4、观察者模式的使用场景:

1、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变

2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节

、观察者模式在ListView和WheelView中的应用

1、我们先来看一下类图:

2、关于上面类图,我们可以发现:

[1]DataSetObserve是观察者

[2]DataSetObservable是被观察者,即角色,它持有很多个观察者对象

[3]DataSetObservable持有DataSetObserve对象

[4]而BaseAdapter中又持有DataSetObservable对象,所以相当于,BaseAdapter也持有DataSetObserve对象
3、接着我们再看ListView中的setAdapter()方法

ListView的setAdapter()方法的源代码我就不贴出来了,我们可以在setAdapter()方法中可以看到这样一句mAdapter.registerDataSetObserver(mDataSetObserver);在BaseAdapter类中我们可以看到registerDataSetObserver()方法的具体实现为:

public voidregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
而该方法又是调用了DataSetObservable中的registerObserve(observer)方法,在DataSetObservable中我们可以看到registerObserve()方法的具体实现为:
public voidregisterObserver(T observer) {
if(observer ==null) {
throw newIllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if(mObservers.contains(observer)) {
throw newIllegalStateException("Observer "+ observer +" is already registered.");
}
mObservers.add(observer);
}
}
所以通过Listview的setAdapter方法,我们就将一个DataSetObserve添加到了Adapter的DataSetObservable中,即给adapter添加了一个观察者
4、下面我们来看一下adapter中notifyDataSetChanged方法的实现过程
当数据有变动时,我们经常通过notifyDataSetChanged方法来刷新界面,在BaseAdapter类中,我们可以看到notifyDataSetChanged方法的具体实现为:
public voidnotifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
我们又可以看到notifyDataSetChanged()方法中仅仅是调用了DataSetObservable中的notifyChanged()方法,接下来我们再来看notifyChanged方法的具体实现:
DataSetObservable类中
public voidnotifyChanged() {
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(inti =mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
我们可以看到,它的实现也很简单,就是通过循环的方式,依次调用每个观察者(DataSetObserver)的onChanged()方法;我们在ListView的setAdapter方法中调用的mAdapter.registerDataSetObserver(mDataSetObserver);方法中的参数mDataSetobserver是一个AdapterDataSetObserver 类型的类,而它又是继承自DataSetObserver类的, 下面我们可以看到AdapterDataSetObserver 类的源码实现:
class AdapterDataSetObserver extends DataSetObserver
{
private Parcelable mInstanceState = null;
AdapterDataSetObserver() {
}
public void onChanged() { mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
if ((getAdapter().hasStableIds()) && (mInstanceState != null) && (mOldItemCount == 0) && (mItemCount > 0))
{
onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}
//...省略不必要代码
}
在该类中我们可以看到调用了requestLayout()方法,该方法就是用来进行页面刷新的
自定义滚轮中AbstractWheelAdapter的实现方式与Android中BaseAdapter的实现方式类似,它也使用了观察者模式,只是他没有使用一个单独的被观察者角色(类似于Android源码中的DataSetObservable类),而是让AbstractWheelAdapter直接持有观察者对象,即AbstractWheelAdapter本身就是一个被观察者,它里面有一个datasetObservers变量用来存储观察者对象。
Android源码的实现方式为,adapter持有被观察者,而被观察者再持有观察者对象。
发布了27 篇原创文章 · 获赞 60 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览