文档章节

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

HanZhang
 HanZhang
发布于 2016/05/14 14:38
字数 1039
阅读 8
收藏 0
点赞 2
评论 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与模式:单例模式

这是我们最常见的一类模式,对这一类模式有一个通用的特点就是: 封装创建的方式和过程。 这里所谓封装就是隐藏的意思,对对象的创建方法和过程不可见,或者是虚拟的过程。 隐藏创建方式,就...

今幕明
2014/03/12
0
0
在Android中探秘建造者模式

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

fyales
2015/03/27
0
0
Android拓展系列(3)--Android源码下载

前几天,又切换回ubuntu11.04系统了,体验以下unity桌面。 android系统源码(包括sdk源码)的下载主要是需要用到git工具,关于git工具的使用我会抽空专门介绍,这里用到的时候简略说明一下。 ...

枫影Xda
2011/10/23
0
0
android 1.6下使用 Loader示例

android 3.0 sdk,引入了很多新api,比如Loader。和Fragment类似(编写兼容android1.6的fragment),该api也可在android 1.6以上版本执行。 以下介绍如何编写Loader,实现对ListView的异步加...

鉴客
2011/03/30
0
0
Android 网络编程 目录

Android 网络编程 目录 Android 网络编程1 Http协议 to be continued... Android 架构师之路 目录 Android 架构师之路1 UML图之用例图 Android 架构师之路2 UML图之类图 Android 架构师之路3...

香沙小熊
06/21
0
0
Android系统源代码分析步骤

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

紫地瓜
2012/11/19
0
0
Android也架构之三:简单工厂模式优化网络请求

很悲催,我们在《Android也架构之二:单例模式访问网络》 用httpConnect的方式去访问网络,而且能够正常获取数据了,可是老板能,技术出生,他要求我重新用httpClient去获取获取网络数据,童...

理工男海哥
2012/08/21
0
0
Android也架构之二:单例模式访问网络

oschina中没有代码插入,看带有代码的文章挺费劲的,如果你和我一样 请移步:http://blog.csdn.net/michaelyy/article/details/7883621 或者我的个人网站 http://www.devchina.com 首先我们来...

理工男海哥
2012/08/19
0
1
Activity的四种加载方式

配置activity时可指定android:launchMode属性,该属性用于配置改Activity的启动模式。该属性支持以下4个属性值。 standard:标准模式,默认的加载模式 singleTop:Task栈顶单例模式 singleTa...

dailei1021
2015/11/21
0
0
试着从java到C去理解android中发送短信的源代码

今天在找GPRS的源代码的时候居然找到了SMS的源代码,那么就写个短信发送功能,并来解释下源代码吧(自己的理解,求别喷)。 首先来个短信发送的小程序吧 String number = "110"; 下面来解释一...

我不是咸蛋
2012/09/04
0
12

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
17分钟前
0
0
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
28分钟前
0
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
34分钟前
0
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
49分钟前
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
56分钟前
0
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
今天
0
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
今天
0
0
安装tensorflow-XXX报错

报错: tensorflow-0.5.0-cp27-none-linux_x86_64.whl is not a supported wheel on this platform. 解决: wget https://bootstrap.pypa.io/get-pip.py sudo python2.7 get-pip.py sudo p......

Yao--靠自己
今天
0
0
JVM学习手册(一):JVM模型

一直从事JAVA开发,天天和JVM打交道,仔细想想对JVM还真的不是特别了解,实在是不应该.周六看了许多资料,也算有点心得,记录一下。 JVM内存模型分为5个区域:方法区,堆,虚拟机栈,本地方法栈,程序计...

勤奋的蚂蚁
今天
0
0
转行零基础该如何学Python?这些一定要明白!

转行零基础学Python编程开发难度大吗?从哪学起?近期很多小伙伴问我,如果自己转行学习Python,完全0基础能否学会呢?Python的难度到底有多大?今天,小编就来为大家详细解读一下这个问题。...

猫咪编程
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部