文档章节

从Android源代码来看『观察者模式』

HanZhang
 HanZhang
发布于 2016/05/14 14:38
字数 1039
阅读 8
收藏 0

这篇文章主要帮助大家理解什么是『观察者模式』,同时结合Android中ListView和BaseAdapter的源代码来解释一下此模式。


###首先,通俗的解释一下什么是『观察者模式』。

『观察者模式』中有两个角色:老板、员工。<br /> 老板可以雇佣和解雇员工,可以命令员工去干活。

我们可以再来看一下百度百科的解释:观察者模式

根据『观察者模式』的字面意思,很可能误解为:『观察者』在检测到『被观察者』发生变化时,自己做出一定反应。 但是,实际上这个『观察者』很懒,说是『观察者』,其实是等到『被观察者』通知他:『我变身了!』,然后『观察者』做出反应。 所以把『观察者』看作『员工』,『被观察者』看作『老板』更为合适,我们也可以叫它『雇佣者模式』吧!


###然后,我们结合代码来看看『观察者模式』。 在Android中,包含了对应观察者模式的两个类:DataSetObserverDataSetObservableDataSetObserver便是『观察者』,就是『员工』,DataSetObservable便是『被观察者』,是『老板』。

DataSetObserver.Java:『员工』有两个函数,代表这老板有权利让他干这两种活。因为这里是Android中BaseAdapter要用到的DataSetObserver,所以『员工』只干这两种活。

public abstract class DataSetObserver {
	public void onChanged() {  
		// Do nothing    
	}    
  	public void onInvalidated() {        
  		// Do nothing    
  	}
}

DataSetObservable.Java:『老板』可以让雇佣的所有员工干活。另外继承Observable后,『老板』拥有了Observable的雇佣和解雇『员工』的能力。

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();
            }
        }
    }
}

Observable.Class:『老板』雇佣和解雇『员工』。(实际上是通过ArrayList来保存和移除『员工』的)

public abstract class Observable<T> {
    public void registerObserver(T observer) {
        ...省略代码
    }
    public void unregisterObserver(T observer) {
        ...省略代码
    }
}

以上便是Android源代码对『观察者模式』的准备。两个抽象类和一个具体类描述了『员工』可以干的活和『老板』的权利。


###那Android中ListView和BaseAdapter是如何利用『观察者模式』的呢?

在Android中我们经常要用到 ListView 组件。ListView 是用来显示一列类似的 ItemView 的。而且不同开发者,对 ItemView 的样式的显示效果的要求是不一样的,可谓千种万种。<br /> 为此,Android 通过增加 Adapter 层,将 ItemView 的操作都封装到 Adapter 中,然后 ListView 拥有一个Adapter对象,通过调用此对象的接口完成多个 ItemView 的布局。这样来看,Adapter 完成了数据层的操作,ListView 是不用涉及到 ItemView 的数据层的。这种模式其实是『适配器模式』的变种。我们以后再看『适配器模式』。

#####那当数据发生改变,要更新 UI 的时候怎么办呢?

Android 的做法是,在 Adapter 中添加一个『老板』对象,让 Adapter 拥有『老板』的所有权利。然后在 ListView 中,添加一个『员工』对象(继承 DataSetObserver,在重写父类方法时,更新 UI)。另外在 ListView 的 setAdapter 方法中,将『员工』和『老板』绑定起来,实现『老板』和『员工』的雇佣关系。最后开发者就可以调用 Adapter 的方法,让『老板』命令『员工』干活了!

接下来我们看一下代码实现。<br /> BaseAdapter.Java: 拥有DataSetObservable对象,就是说Adapter是『老板』的上司,拥有『老板』的所有权利。

public abstract class BaseAdapter {
    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();
    }
}

**ListView.Java:**setAdapter()方法中,将 AdapterDataSetObserver 注册到 Adapter 的DataSetObservable中,实现『老板』和『员工』的雇佣关系。

public class ListView {
	...代码省略
	[@Override](https://my.oschina.net/u/1162528)
    public void setAdapter(ListAdapter adapter) {
    	...代码省略
    	mDataSetObserver = new AdapterDataSetObserver();
    	mAdapter.registerDataSetObserver(mDataSetObserver);
    	...代码省略
    }
    ...代码省略
}

AdapterDataSetObserver 继承了 DataSetObserver,重写父类函数时,进行更新界面的操作。

『观察者模式』实现了对数据和界面的解耦。


以上就是笔者对『观察者模式』的理解了,若有谬误,敬请指出!谢谢!

© 著作权归作者所有

共有 人打赏支持
HanZhang
粉丝 1
博文 42
码字总数 24925
作品 0
武汉
程序员
私信 提问
Android程序员的晋级之路

Android移动开发程序员的职业发展路径。 晋升轨迹:Android初级开发程序员---中级---高级--软件架构师--系统架构师--项目经理--首席技术官 各阶段对于技能要素的要求:    入门初级阶段:...

SunnyTime
2016/09/27
1K
13
Android - 硬件抽象层(HAL)

出发点:保护厂商利益 Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User ...

天王盖地虎626
01/11
0
0
把Android源代码加入SDK

各位调试Android程序的时候遇到“source not found”错误应该很抓狂吧,Goolge在发布SDK时没有把源代码包含进去着实有点让人费解,对很多人来说Git无疑是个生涩的东西,而 framework中所有J...

黄平俊
2009/07/09
25.3K
7
在Android中探秘建造者模式

前言 在Android开发过程中,我发现很多安卓源代码里应用了设计模式,比较常用的有适配器模式(各种adapter),建造者模式(Alert Dialog的构建)等等。虽然我们对大多数设计模式都有所了解,但是...

fyales
2015/03/27
0
0
Android系统源代码分析步骤

目前,互联网行业正在朝着移动互联网方向强劲地发展,而移动互联网的发展离不开背后的移动平台的支撑。众所周知,如今在移动平台市场上,苹果的iOS、谷歌的Android和微软的Windows Phone系统...

紫地瓜
2012/11/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

弹窗时候禁止页面滚动

1、依靠css 将页面 document.documentElement.style.overflow='hidden'; document.body.style.overflow='hidden';//手机版设置这个。 如果设置了如上,页面的滚动条将会消失,此时鼠标滚轮失......

Jack088
14分钟前
1
0
.NET的数学库NMath实用教程——创建最小二乘法

NMath是一个适用于所有.NET语言,如C#、Visual Basic、F#和.NET的数学库,它包含了.NET平台上的面向对象数字计算的基础类。我们将以连载的形式向大家介绍NMath的实用教程,有任何建议或提示...

ymy_666666
14分钟前
1
0
索尼为收购工作室准备,对抗微软?

对比来说,索尼方面不但没有增加新的工作室,反而在过去两年内关闭了一些工作室。面对微软的步步紧逼,索尼最新的招聘广告暗示将来有可能会收购一些工作室。 在领英上,索尼互动娱乐发布了两...

linuxCool
15分钟前
1
0
公司网站有漏洞被入侵该怎么解决

2019年1月14日消息,thinkphp又被爆出致命漏洞,可以直接远程代码执行,getshell提权写入网站木马到网站根目录,甚至直接提权到服务器,该漏洞影响版本ThinkPHP 5.0、ThinkPHP 5.0.10、Think...

网站安全
27分钟前
2
0
centos7 Nginx+rtmp 搭建流媒体服务器

一. gcc 安装 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装: yum -y install gcc gcc-c++ 二. PCRE pcre-devel 安装 PCRE(Perl Compatib...

legend3
44分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部