`

经典软件设计模型 - 事件驱动模型

 
阅读更多

模型说明

在UI编程中,常常要对鼠标点击进行相应,首先如何获得鼠标点击呢?
方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点:
1. CPU资源浪费,可能鼠标点击的频率非常小,但是扫描线程还是会一直循环检测,这会造成很多的CPU资源浪费;如果扫描鼠标点击的接口是阻塞的呢?
2. 如果是堵塞的,又会出现下面这样的问题,如果我们不但要扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被堵塞了,那么可能永远不会去扫描键盘;
3. 如果一个循环需要扫描的设备非常多,这又会引来响应时间的问题;
所以,该方式是非常不好的。

方式二:就是事件驱动模型
目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:
1. 有一个事件(消息)队列;
2. 鼠标按下时,往这个队列中增加一个点击事件(消息);
3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;
如图:

 

Android的Looper和Handler模型

在Android系统中,一般的事件驱动应用都可以使用Looper和Handler来实现,uml如下

UML



说明

Message是一个个的消息,每个消息代表一个事件,每个Message都有独立的处理者target;
多个消息利用Message里的next属性首尾相接组成一个MessageQueue队列;
MessageQueue提供了插入Message接口enqueueMessage和读取Message接口next;
Looper是一个循环类,它利用MessageQueue的next接口,不断从MessageQueue获得消息;
如果Looper获得了一个消息Message,那么就调用Message的target来处理该消息,这个target其实就是一个Handler;
Handler的HandlerMessage函数就是处理Message的地方,这是一个接口函数,所以使用者根据业务需求重写这个接口;
Handler除了处理Message外,还提供了插入Message的接口sendMessage,从这也可以看出,利用这四个类设计最简单的事件驱动模型只需操作Hanlder一个类即可,因为它既提供了插入消息的接口,也提供了处理消息的接口;

当然这四个类除了MessageQueue之外,其他三个用户都可以根据业务需求操作实现更复杂的模型,我们可以自己创建一个Message而不是使用Message的默认创建方法(如可以为每个Message设计不同的处理函数,不一定使用HandlerMessage),然后通过Handler插入到消息队列中;然后创建自己的Looper线程,自己独自使用一个Looper;之所以MessageQueue不能自行设计,是因为Android的设计问题,因为MessageQueue是在Looper的构造函数自己new的。

重点代码分析

Handler的handleMessage优先级

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * Subclasses must implement this to receive messages. 
  3.  */  
  4. public void handleMessage(Message msg) {  
  5. }  
  6.   
  7. /** 
  8.  * Handle system messages here. 
  9.  */  
  10. public void dispatchMessage(Message msg) {  
  11.     if (msg.callback != null) {  
  12.         handleCallback(msg);  
  13.     } else {  
  14.         if (mCallback != null) {  
  15.             if (mCallback.handleMessage(msg)) {  
  16.                 return;  
  17.             }  
  18.         }  
  19.         handleMessage(msg);  
  20.     }  
  21. }  


looper读取一个消息后,首先执行的是dispatchMessage,然后dispatchMessage根据不同条件调用不同的handleMessage;
这里边有好多callback,是因为不一定非要使用Handler提供的handleMessage接口处理消息,也可以有很多其他方式设置回调函数; 
优先级最高的是msg.callback,如果要处理的Message本身有处理回调接口,那么就使用Message本身的;
优先级次之的是mCallback,mCallback是在Handler的构造函数设置的,说明可以为Handler统一设置一个处理回调接口;
优先级最低的是handleMessage,这个才是handleMessage用户重写的接口;

设置这些优先级,主要为了在应用中需要处理的消息有很多种分类,但是它们共用一个Looper,如
1. 如果所有的消息属于一个分类,那么只需要一个Handler即一个handleMessage即可;
2. 如果消息分属于不同的分类,那么每个分类使用一个Handler管理,即每个分类使用一个handleMessage,即mCallback;
3. 如果所有的消息种类都不一样,如果使用一个Handler在逻辑上不伦不类,所以,这个时候不如为每个消息设置一个回调函数更好,即msg.callback;

 

MessageQueue的时间优先级when
Handler是通过enqueueMessage接口将消息插入到MessageQueue的,在插入的时候就已经将消息按照时间排序了,其中时间0代表最高的优先级,时间越大,优先级越小,越延后处理
所以,Looper通过MessageQueue的next接口获得的消息就是优先级最高的消息,next不需要重新排序消息队列了;

 

HandlerThread的作用

如果我们需要自己创建Looper,需要将创建的Looper和创建的Handler联系在一起。如果两个对象的创建是在一个线程里,并且先创建Looper后创建Handler是没有问题的;但是如果两个对象是在两个线程里创建,有可能在构造Handler时,Looper并没有真正的创建好,其实这之间只要通过一个同步就可以。HandlerThread就是Android提供给我们用的一个类,它已经做好了同步,所以可以安全使用。

分享到:
评论

相关推荐

    基于模型-数据-知识驱动和深度学习的地表温度反演方法

    《基于模型-数据-知识驱动和深度学习的地表温度反演方法》 地表温度反演是遥感领域中的一个重要研究课题,对于气候变化监测、环境管理和灾害预警具有重要意义。传统的地表温度(LST)反演算法往往依赖于先验知识,...

    并发编程-事件驱动模型1

    【并发编程-事件驱动模型1】 并发编程是现代软件开发中的关键组成部分,它允许程序同时处理多个任务,提高系统的效率和响应性。事件驱动模型是一种常见的并发编程模型,尤其适用于网络服务器和用户界面(UI)应用...

    Simulink仿真模型-逆变驱动(SPWM驱动)

    Simulink仿真模型-逆变驱动(SPWM驱动)

    mda-模型驱动体系结构_PPT

    - **模型驱动**:指的是利用模型来进行软件的分析、设计、构建、部署和维护等一系列活动。 - **体系结构**:是指构成系统的组件、它们之间的连接方式以及约束这些组件和连接方式的规则。 - **MDA的起源**:起源于将...

    医疗设备软件开发-模型驱动.pdf

    医疗设备软件开发-模型驱动.pdf

    模型驱动的软件开发模式研究.pdf

    模型驱动的软件开发模式的理论基础来自于模型驱动的设计方法论,包括模型驱动的设计语言、模型转换和代码生成技术等。模型驱动的设计方法论强调了模型在软件设计中的核心作用,以模型为中心的设计方法可以提高软件...

    事件驱动模型实例详解(Java篇)

    事件驱动模型是现代软件开发中一种关键的编程模式,尤其在图形用户界面(GUI)编程中占据核心地位。该模型围绕三个核心概念构建:事件源、侦听器以及事件处理程序。事件源可以是任何能产生事件的对象,例如用户界面...

    Generic 16BW-5 驱动

    GDI(Graphics Device Interface)驱动是Windows操作系统中的一种图形驱动模型,它允许应用程序通过标准接口与各种图形设备进行通信,而无需了解底层硬件的具体细节。GDI驱动通常用于处理基本的图形和文本渲染,如...

    领域驱动模型(DDD).zip_ddd_领域模型_领域驱动_领域驱动设计

    通过学习《领域驱动模型(DDD).pdf》这样的资料,开发者可以深入了解DDD的原理,掌握如何进行领域建模,如何划分限界上下文,如何设计和实现业务规则,以及如何有效地与其他团队成员协作,以实现高质量、符合业务...

    Java 开发中事件驱动模型的实例详解

    在Java开发领域,事件驱动模型(Event-Driven Model)是一种广泛采用的设计模式,它通过响应外部事件来触发程序中的特定行为。本文将深入探讨Java中事件驱动模型的应用,特别是通过Swing框架的具体实例来解析这一...

    化繁为简--DDD驱动复杂业务软件架构的演进(33页).pdf

    《化繁为简--DDD驱动复杂业务软件架构的演进》是关于如何通过领域驱动设计(DDD)来解决复杂业务软件架构问题的报告。报告由广联达科技的白彦磊撰写,共计33页,详细阐述了在建筑行业中如何运用DDD方法论,以应对...

    领域驱动设计与模型驱动开发

    综上所述,领域驱动设计和模型驱动开发是软件开发领域内的重要思想,它们通过强调领域模型的核心作用、清晰的分层架构以及基于模型的开发实践,帮助软件开发团队在面对复杂业务逻辑时能够构建出结构清晰、易于扩展和...

    模型驱动--MDA简介

    模型驱动--MDA简介 模型驱动是一种软件开发方法,它强调模型在软件开发中的核心作用。...模型驱动的软件开发方法是一种高效、灵活的软件开发方法,它可以帮助开发人员更好地设计、开发和维护软件系统。

    领域驱动设计案例-盒马实践

    本文将通过对盒马实践的领域驱动设计案例进行详细的分析,讨论领域模型的设计理念、数据建模、对象建模、依赖注入等方面的知识点。 领域模型的设计理念 领域模型是领域驱动设计的核心概念,它指的是对业务领域的...

    模型驱动软件设计 UML MDA

    **模型驱动软件设计**是一种先进的软件开发方法论,它的核心思想是将软件开发的重点从代码编写转移到了模型创建。在这一方法中,软件系统的设计、分析、实现和维护都通过可扩展标记语言(XML)表示的模型来完成,极...

    SpringBoot整合RabbitMQ之Spring事件驱动模型-系统源码数据库流程图

    SpringBoot整合RabbitMQ之Spring事件驱动模型-系统源码数据库流程图 SpringBoot整合RabbitMQ实战视频教程:https://edu.csdn.net/course/detail/9314 (感兴趣也可以加QQ联系:1974544863)

    "深入解析TCU变速箱控制器仿真模型:集成设计文档与算法模块,涵盖驱动制动、电机传动及车辆数学模型,实现AMT TCU应用层软件功能模块的量产应用",TCU变速箱控制器仿真模型-含(设计文档) 乘用车

    "深入解析TCU变速箱控制器仿真模型:集成设计文档与算法模块,涵盖驱动制动、电机传动及车辆数学模型,实现AMT TCU应用层软件功能模块的量产应用",TCU变速箱控制器仿真模型-含(设计文档) 乘用车AMTTCU变速箱控制器...

    事件驱动模型

    事件驱动模型是一种软件设计模式,它基于异步通信和消息传递的概念来构建应用程序。在这种模型中,系统的行为是由发生的事件来触发的,而不是由预先设定的顺序执行的指令。事件可以是用户操作、硬件状态改变、定时器...

    Linux驱动程序开发-设备驱动模型

    Linux 驱动程序开发 - 设备驱动模型 Linux 驱动程序开发 - 设备驱动模型是 Linux 操作系统中的一种设备管理机制,负责管理和控制各种设备。 Linux 2.6 设备驱动模型的基本元素是 Class、Bus、Device、Driver,下面...

Global site tag (gtag.js) - Google Analytics