Android源码学习之观察者模式应用及优点介绍

观察者模式定义:

Define a one-to-many dependency between objects so that when one object changes state, all its dependents aer notified and updated automatically.

定义对象间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

 

如上图所示(截取自《Head First Design Patterns》一书),主要包括四个部分:

1. Subject被观察者。是一个接口或者是抽象类,定义被观察者必须实现的职责,它必须能偶动态地增加、取消观察者,管理观察者并通知观察者。

2. Observer观察者。观察者接收到消息后,即进行update更新操作,对接收到的信息进行处理。

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

4. ConcreteObserver具体观察者。每个观察者在接收到信息后处理的方式不同,各个观察者有自己的处理逻辑。

观察者模式有什么优点呢:

观察者和被观察者之间是抽象耦合的,不管是增加观察者还是被观察者都非常容易扩展。

根据单一职责原则,每个类的职责是单一的,那么怎么把各个单一的职责串联成真实的复杂的逻辑关系呢,观察者模式可以起到桥梁作用。

观察者模式是松耦合的典型。

在Android源码中,其中一个经典的使用到观察者模式的就是Android控件的事件监听模型。

一、下面简要说明Android交互事件传输的设计原理和特征:

交互事件,是指当用户通过按键、触摸、滑动等操作与应用进行交互时触发的相关事件。通过Android控件树可知,交互事件是沿着控件树自顶向下传播的。其中Android控件树简要图如下所示:

 

当位于控件树上层的父控件收到交互事件后,会先行判定该事件的目标控件对象,如果该事件正是自己所需要的,则会截获事件进行处理,否则就尝试将事件向下分发给对应的子控件,并对推的逐级向下传播事件,直至该事件被处理或者忽略。

Android在View类中定义了一系列命名为View.On***的事件函数用来接收和处理各类交互事件,如通过View.OnKeyDown函数可以接收到用户的按键操作等。每个派生自View类的子控件都可以通过重载这些事件函数,来处理该控件所需的事件。

例如,如果一个控件需要处理用户按返回键的操作,则可以通过重载View.onKeyDown函数来实现:

复制代码 代码如下:

/*

* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)

*/

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

// 监听和处理返回操作

if(keyCode == KeyEvent.KEYCODE_BACK) {

doSomething();

return true;

}

return false;

}

事件函数的返回值是控制事件传播的重要手段。如果事件函数返回true,则说明该控件已经接收并完成了该事件的处理,无须将该事件进一步传递;反之,如果事件函数返回false,则说明该控件对象未能处理该事件(或虽然做过处理,但仍需要进一步处理),需要继续传递以寻找能够处理它的控件对象。

对于容器控件ViewGroup来说,它的一个职责就是将交互事件传播到其子控件中。针对不同的事件,ViewGroup可以选择不同的传播方式。如,如果是触摸事件,ViewGroup对象需要判定该事件发生的区域位于哪个子控件上,从而将该事件分配给该子控件进行处理。但通过继承的方式来进行事件处理并不够灵活,会导致系统中出现大量的子控件类型,并且各个控件的复用性都较差。因此采用“组合”来代替“继承”。基于此思想,View类中提供了一系列配套的事件监听函数供开发者处理对应事件,这就有了使用观察者模式来完成Android控件的事件监听模型。开发者可以构造外部观察者对象与控件对象的事件监听接口绑定,获取事件消息。

还是以上面的按键事件为例,通过监听者进行处理的实现如下所示:

复制代码 代码如下:

final View.OnKeyListener listener = new OnKeyListener() {

@Override

public boolean onKey(View v, int keyCode, KeyEvent event) {

// 处理返回键事件

if(keyCode == KeyEvent.KEYCODE_BACK) {

doSomething();

return true;

}

return false;

}

};

。。。

mUISetButton = (Button) findViewById(R.id.setValue);

// 将按钮与监听对象绑定

mUISetButton.setOnKeyListener(listener);

通过利用外部对象来处理交互事件,其耦合性低,使每个类控件都具有更好的可复用度,无须为了处理事件而构造新的控件。

二、现在开始看看源代码是怎么进行组织使用“观察者模式”的

1. 看View类源代码中的OnKeyListener接口:

复制代码 代码如下:

/**

* Interface definition for a callback to be invoked when a key event is

* dispatched to this view. The callback will be invoked before the key

* event is given to the view.

*/

public interface OnKeyListener {

/**

* Called when a key is dispatched to a view. This allows listeners to

* get a chance to respond before the target view.

*

* @param v The view the key has been dispatched to.

* @param keyCode The code for the physical key that was pressed

* @param event The KeyEvent object containing full information about

* the event.

* @return True if the listener has consumed the event, false otherwise.

*/

boolean onKey(View v, int keyCode, KeyEvent event);

}

2. 再看View类定义了私有成员mOnKeyListener(通过组合的方式):

private OnKeyListener mOnKeyListener;

3. 注册listener

复制代码 代码如下:

/**

* Register a callback to be invoked when a key is pressed in this view.

* @param l the key listener to attach to this view

*/

public void setOnKeyListener(OnKeyListener l) {

mOnKeyListener = l;

}

4. 剩下的就交给开发者自己构造外部观察者对象与该按键的事件接口进行绑定,获取事件消息。

最后让我们记住支撑“观察者模式”的设计原则: Strive for loosely coupled designs between objects that interact.

时间: 2024-10-24 05:00:47

Android源码学习之观察者模式应用及优点介绍的相关文章

Android源码学习之单例模式应用及优点介绍_Android

单例模式定义: Ensure a class has only one instance, and provide a global point of access to it. 动态确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.     如上图所示(截取自<Head First Design Patterns>一书). 通过使用private的构造函数确保了在一个应用中产生一个实例,并且是自行实例化(在Singleton中自己使用new Singleton()). 具体单

Android源码学习之单例模式应用及优点介绍

单例模式定义: Ensure a class has only one instance, and provide a global point of access to it. 动态确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 如上图所示(截取自<Head First Design Patterns>一书). 通过使用private的构造函数确保了在一个应用中产生一个实例,并且是自行实例化(在Singleton中自己使用new Singleton()). 具体单例模式有

Android源码学习之组合模式定义及应用_Android

组合模式定义: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. 将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. 如上图所示(截取自<Head First De

Android源码学习之组合模式定义及应用

组合模式定义: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. 将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. 如上图所示(截取自<Head First De

Android源码学习之工厂方法模式应用及优势介绍

工厂方法模式定义: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 常用的工厂方法模式结构: 如上图所示(截取自<Head Firs

如何学习android源码中的framework,只有java基础

问题描述 如何学习android源码中的framework,只有java基础 求大神指导,如何学习framework?源码里面东西太多,感觉找不到入口 解决方案 从写android应用软件开始,或者上网收集framework的一些讲解资料,网上特别多 解决方案二: 你怎么学习的java就怎么学习Android 解决方案三: 除了努力還是努力加油 解决方案四: 围绕AMS和WMS展开,Android系统核心就这两个,弄懂了这两个服务如何和应用交互的,基本就了解Android系统的运行原理了. 解决

对于android源码的一些看法

1.背景 即将结束在sony移动的实习了,在最后的日子有一些伤感有一些感触,对于android这个倾注一年心血的技术有太多话要说.感谢sony移动的各位大牛们给我这个机会,让我彻彻底底的看清了android的本质.没有这次工作经历,我对android的印象可能会一直停留在sdk层.这一年陆陆续续的写关于android方面的博客,算上这一篇应该正好20篇.从最初的介绍一些小控件的使用,到现在写一些简单的源码操作,是时候写一篇总结了... 2.需要的资料 胡乱扯一下学习android源码所需要的便利

Android 源码分析,FreeMind 是一件超级利器

Android 源码分析,FreeMind 是一件超级利器 思维导图软件 XMind 与 FreeMind 的对比 作者: 善用佳软 日期: 2012-04-17 分类: 1 文本办公, 1.5 思维导图 标签: mindmap 思维导图类软件中,最有影响力的开源免费软件是 FreeMind 和 XMind.FreeMind历史悠久,当属经典:XMind作为后起之秀,大有赶超之势.同作为免费.开源的思维导图解决方案,应如何选择/结合两款软件?本文试做分析,以供用户/开发者参考. 本文的分析基于W

《Android 源码设计模式解析与实战》——导读

目 录 自序一 自序二 前言 致谢 第1章 走向灵活软件之路--面向对象的六大原则 1.1节优化代码的第一步--单一职责原则1.2节让程序更稳定.更灵活--开闭原则1.3节构建扩展性更好的系统--里氏替换原则1.4节让项目拥有变化的能力--依赖倒置原则1.5节系统有更高的灵活性--接口隔离原则1.6节更好的可扩展性--迪米特原则1.7节总结 第2章 应用最广的模式--单例模式 2.1节单例模式介绍2.2节单例模式的定义2.3节单例模式的使用场景2.4节单例模式UML类图2.5节单例模式的简单示例