标题 | Android源码中观察者模式的运用 |
范文 | 单丹丹 韩冬 摘要:该文介绍了设计模式中观察者模式的基本概念,在理解观察者模式的基础上,对Android源码中观察者模式的运用进行了深入的分析,说明了观察者模式在程序设计中的重要性。 关键词:设计模式;观察者模式;Android源码 中图分类号:TP311 文献标识码:A文章编号:1009-3044(2017)02-0068-02 1觀察者模式介绍 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 2观察者模式使用场景 1)当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。 2)当对一个对象的改变需要同时改变其他对象, 而不知道具体有多少对象需要被改变。 3)当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之, 不希望这些对象是紧密耦合的。 3观察者模式中的角色及UML类图表示 1)抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。 2)具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。 3)抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。 4)具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。 用UML类图表示如下: 4 观察者模式的Android源码实现 Adapter是ListView中最重要的一个点。向ListView中添加数据后,都会调用notifyDataSetChanged()方法。notifyDataSetChanged方法定义在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();}} 上段代码中mDataSetObservable.notifyChanged()函数代码如下: public class DataSetObservable extends Observable public void notifyChanged() { synchronized(mObservers) { // 遍历调用所有观察者的onChanged方式 for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged();}}} // 代码省略 } 上段代码中的观察者由ListView通过setAdapter方法来设置Adapter时构建的AdapterDataSetObserver创建,代码如下: 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(); // 创建一个一个数据集观察者
mDataSetObserver = new AdapterDataSetObserver(); // 将这个观察者注册到Adapter中,实际上是注册到DataSetObservable中 mAdapter.registerDataSetObserver(mDataSetObserver); // 代碼省略 } else {// 代码省略 } requestLayout();} 通过以上的代码,被观察者、观察者都已经被创建。 下面具体说明AdapterDataSetObserver是如何运作。AdapterDataSetObserver定义在ListView的父类AbsListView中,代码如下 : class AdapterDataSetObserver extends AdapterView public void onChanged() { super.onChanged(); if (mFastScroller != null) { mFastScroller.onSectionsChanged();}} //代码省略 } 同时AdapterDataSetObserver又继承自AbsListView的父类AdapterView的AdapterDataSetObserver。当ListView的数据发生变化时,会调用Adapter的notifyDataSetChanged函数,这个函数中会调用DataSetObservable的notifyChanged函数,notifyChanged函数又会调用所有观察者的onChanged方法。这就是一个观察者模式! 最后我们对观察者模式的源码实现进行一个梳理:AdapterView中有一个内部类AdapterDataSetObserver,在ListView设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中,这就是一个观察者。而Adapter中包含一个可观察者数据集DataSetObservable,在数据数量发生变更时,开发者手动调用AdapternotifyDataSetChanged,而notifyDataSetChanged实际上会调用DataSetObservable的notifyChanged函数,该函数又会遍历所有观察者的onChanged函数。在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,从而对用户界面进行更新。 上述代码可以运用于杂志订阅的事例中,杂志是主题,观察者是订阅者,当出版新杂志时候,这个事件会自动通知所有的订阅者。除此以外也可以运用于气象站,为气象站提供用户订阅气象信息的服务。总是,观察者模式在日常生活中的运用十分广泛。 5观察者模式总结 观察者模式的主要的作用就是对对象解耦,将观察者和被观察者完全隔离。 1)观察者模式的优点 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。 2)观察者模式的缺点 在应用观察者模式时需要考虑一下开发小路问题,程序中包括一个被观察者和多个被观察者额,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。 3)观察者模式的重要性 观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,它可以将消息一一通知给所有的观察者。观察者模式基于接口而不是具体的实现的特点,为程序设计提供了更大的灵活性,在程序设计中有着重要的地位。 参考文献: [1] 何红辉,关爱民.Android源码设计模式解析与实战[M].北京:人民邮电出版社, 2015:224-245. [2] 何宏辉.Android开发进阶从小工到专家[M].北京:人民邮电出版社, 2016:195-215. [3] 郭霖.第一行代码[M].北京:人民邮电出版社, 2014:127-135. [4] 李刚.疯狂安卓讲义[M].北京:电子工业出版社, 2015:88-97.
|
随便看 |
|
科学优质学术资源、百科知识分享平台,免费提供知识科普、生活经验分享、中外学术论文、各类范文、学术文献、教学资料、学术期刊、会议、报纸、杂志、工具书等各类资源检索、在线阅读和软件app下载服务。