事件和消息机制的理解

消息/事件机制是几乎所有开发语言都有的机制,并不是deviceone的独创,在某些语言称之为消息(Event),有些地方称之为(Message). 其实原理是类似的,只不过有些实现的方式要复杂一点。我们deviceone统一就叫消息.

消息基础概念

还有一些初学者不太熟悉这个机制,我们先简单介绍一些基础概念,如果熟悉的人可以跳过这个部分。
一个/条消息可以理解为是一个数据结构,包含以下几个基本部分:

  1. 消息源 :就是消息的来源,发出这个消息的对象
  2. 消息名 :就是消息的唯一标示
  3. 消息数据:消息发出后附带的数据,有可能数据是空

消息从种类上又可以分为2种:

  1. 系统消息 :由操作系统或deviceone系统发送出来的消息,消息的名称是固定的。
  2. 自定义消息:由开发者自己定义,自己发送出来的消息,消息的名字是随意的,可以任意定义。

举例说明:
比如用户点击一个do_Button按钮,就会触发一个系统消息,包含3个部分:

  1. 消息源:用户点中的button对象
  2. 消息名:touch
  3. 消息数据:这个消息没有附带数据

比如用户通过do_Button按钮触发一个自定义事件,包含3个部分:

  1. 消息源: button对象
  2. 消息名:用户随便定义,叫aaa,bbb,ccc都可以
  3. 消息数据:附带的数据由触发消息的时候设定

发布/订阅模式

发布/订阅模式是最常用的设计模式之一,是消息机制的核心,其特点就是降低耦合度,让二个独立的对象不互相依赖。简单介绍一下,熟悉的同学可以跳过。
我们先从现实的一个简单例子来说明这个问题,参考下图:

从这个图我们可以看出

  1. 消费者和出版社互相不认识,消费者不需要了解他想要的杂志是具体哪家出版社出的;出版社也不需要了解具体是哪个人定了他们出版社发行的书。
  2. 消费者和出版社必须都认识邮局。
  3. 消费者需要告诉邮局消费者的名字地址以及想要订阅的杂志名字
  4. 可以多个消费者订阅同一本杂志
  5. 邮局拿到杂志后,会一一通知消费者,通知的时候同时把杂志送到消费者手里。

看完上面现实例子,我们再来看抽象的描述会更清晰一点,看下图:

和上面的实际例子描述一一对应:

  1. 系统/开发者和函数对象互相不依赖,系统/开发者只管触发一个消息,并不关心谁去接受
  2. 系统/开发者和函数对象必须能获取到消息源对象
  3. 函数对象订阅消息的时候需要标示消息的名称和函数对象的引用
  4. 可以多个函数对象订阅同一个消息源同一名字的消息
  5. 消息源触发消息会一一通知所有订阅者,并把data数据传递到回调函数对象

看完抽象的描述,我们最后来看实际的deviceone开发的例子,还是以do_Button为例子。

1. 当用户点击一个button,触摸到的时候,系统会获取到button这个对象作为消息源,fire一个”touch”消息,任何订阅了”touch”消息的函数对象都会接收到这个消息并引起函数的执行。
  1. //获取button对象
  2. var btn_hello = ui("btn_hello");
  3. //定义函数对象
  4. function f1(){
  5. //当btn_hello这个按钮接收到手指点击就会执行下面的代码
  6. deviceone.print("f1 函数接收到点击触发消息")
  7. }
  8. function f2(){
  9. //当btn_hello这个按钮接收到手指点击就会执行下面的代码
  10. deviceone.print("f2 函数接收到点击触发消息")
  11. }
  12. //f1,f2订阅button的touch消息
  13. btn_hello.on("touch",f1);
  14. btn_hello.on("touch",f2);
2. 我们可以为button对象定义2个自定义的消息”message1”和”message2”,分别有2个函数对象订阅这2个消息。但是最后要触发这个消息必须是开发者通过调用fire函数才能触发,这就是和系统消息的区别。
  1. //获取button对象
  2. var btn_hello = ui("btn_hello");
  3. //定义函数对象
  4. function f1(d){
  5. //当btn_hello这个按钮接收到开发者触发的消息message1就会执行下面的代码
  6. deviceone.print("f1 函数接收到message1消息,消息的数据是:"+d)
  7. }
  8. function f2(d){
  9. //当btn_hello这个按钮接收到开发者触发的消息message2就会执行下面的代码
  10. deviceone.print("f2 函数接收到message2消息,消息的数据是:"+d)
  11. }
  12. //f1,f2订阅button的touch消息
  13. btn_hello.on("message1",f1);
  14. btn_hello.on("message2",f2);
  15. //触发消息
  16. btn_hello.fire("message1","data1");
  17. btn_hello.fire("message2","data2");

看到这里,你肯定会奇怪,为什么我们要在button上自定义对象?这有神马意义?其实确实没有意义也没有必要,这里只是拿button举例子,在常规的开发中,基本不会这么用。

消息的使用

前面讲了这么多,现在才是deviceone消息的使用。使用其实很简单,上面的例子基本说明的了系统事件和自定义事件的使用方法。
有几个概念再说明一下

1.deviceone的所有对象,包括UI,MM,SM对象都可以是消息源
  1. // SM对象可以是消息源
  2. var page = sm("do_Page");
  3. page.on("loaded",function()){
  4. // 这个是page对象的系统消息,这个消息不需要手动触发,系统会自动触发
  5. }
  6. page.on("message1",function(d)){
  7. // 这个是page对象的自定义消息
  8. }
  9. page.fire("message1","data1");
  10. // MM对象可以是消息源
  11. var http = mm("do_Http");
  12. http.on("result",function()){
  13. // 这个是http对象的系统消息,这个消息不需要手动触发,接受到http服务端的反馈后会自动触发
  14. }
  15. http.on("message1",function(d)){
  16. // 这个是http对象的自定义消息
  17. }
  18. http.fire("message1","data1");
  19. //UI对象可以是消息源
  20. var alayout = ui("alayout_id1");
  21. alayout.on("touch",function()){
  22. // 这个是alayout对象的系统消息,这个消息不需要手动触发,手机点击就会触发
  23. }
  24. alayout.on("message1",function(d)){
  25. // 这个是alayout对象的自定义消息
  26. }
  27. alayout.fire("message1","data1");
2.消息源对象有作用域,所以订阅和触发的消息源必须是是一个作用域的同一个对象。这里结合数据分享和数据传递文档来理解。

看以下的例子,test1.ui和test2.ui有可能在一个page作用域,也有可能不在一个作业域,只有在一个作用域fire的消息才能正确送达回调函数。
判断是否一样,可以通过打印page的地址 page.getAddress().

  1. //在test1.ui.js里订阅消息
  2. var page = sm("do_Page");
  3. deviceone.print(page.getAddress());
  4. page.on("message1",function(d)){
  5. deviceone.print(d);
  6. }
  7. //在test2.ui.js触发消息
  8. var page = sm("do_Page");
  9. deviceone.print(page.getAddress());
  10. page.fire("message1","data1");

如果不在同一page作用域,则可以把消息订阅在2个page都能共享到的app作用域
上面的代码改成:

  1. //在test1.ui.js里订阅消息
  2. var app = sm("do_App");
  3. app.on("message1",function(d)){
  4. deviceone.print(d);
  5. }
  6. //在test2.ui.js触发消息
  7. var app = sm("do_App");
  8. app.fire("message1","data1");
3.同样的函数对象可以重复订阅一个对象源的消息,触发消息的时候会使函数执行多次,这是初学者经常犯的错误。
  1. var page = sm("do_Page");
  2. var count = 0;
  3. function f(){
  4. deviceone.print("执行次数"+(count++));
  5. }
  6. page.on("message1",f);
  7. page.on("message1",f);
  8. page.fire("message1");

看上面的例子,如果执行的话,会打印2此,因为订阅了2次,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来执行了重复的on函数,实际情况经常是比如在点击事件里执行on函数,每点击一下按钮,就重复订阅一次。

4.消息的订阅一定要在消息的触发之前,这是初学者经常犯的错误。
  1. var page = sm("do_Page");
  2. var count = 0;
  3. function f(){
  4. deviceone.print("执行次数"+(count++));
  5. }
  6. page.fire("message1");
  7. page.on("message1",f);

看上面的例子,如果执行的话,会没有效果,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来顺序反了,实际情况经常是比如on函数执行在某一个函数的回调函数里,你无法确定回调函数啥时候执行,是否是在fire之前执行。一般碰到这种情况可以加几个deviceone.print打印一下看看是on先执行还是fire先执行。

5.有订阅就有取消订阅,取消订阅是off函数,之所以很少用,是因为closePage的时候会自动把当前page作用域订阅的消息全部释放。但是如果消息订阅在app作用域,就要注意,可能需要手动去取消订阅。否则就会出现触发消息的时候会使函数执行多次的问题。
  1. var page = sm("do_Page");
  2. var count = 0;
  3. function f(){
  4. deviceone.print("执行次数"+(count++));
  5. }
  6. page.on("message1",f);
  7. page.fire("message1");
  8. page.off("message1");
  9. page.fire("message1");

看上面的例子,打印只会执行一次,因为fire一次后就取消订阅了。

时间: 2024-11-03 22:01:40

事件和消息机制的理解的相关文章

ble协议栈cc2540x-1.3.2之通过key处理过程看任务、事件、消息机制

一   事件机制 每一个任务都会有很多种事件,包括系统消息.任务事件等等. 二   事件的触发启动 函数1:启动一个定时器.定时delaytime时间.之后触发TaskID的event事件.延时时间以ms为单位. osal_start_timerEx( TaskID, event,delaytime); 函数2:置 tasksEvents[]数组的事件标志位为1.系统轮询这个数组确定是否触发事件 osal_set_event( simpleBLEPeripheral_TaskID, SBP_ST

谈谈我对Android中的消息机制的理解之Handler,Looper和MessageQueue的解释

Handler的作用是:发送Message和处理Message,handler发送的Message其实就是发送给自己的对象进行处理,所以谁发送就是谁处理,但是这个绝对有意义,以为这样我们就可以通过Handler将消息的处理从一个线程转到另一个线程了,这个Message几经转手之后,处理它的对象虽然是同一个,但是处理它的线程就变了,变成了创建Handler对象的线程,而不是产生Message对象的线程(当然,这个两个线程可能是一个,但是这样使用handler就是第二个目的了),使用handler的

从0 开始 WPF MVVM 企业级框架实现与说明 ---- 第一讲 WPF中 windows消息机制

谈到桌面应用程序,我们第一反应就是它的消息机制是怎么处理的,那么我们就先聊聊这个windows消息机制 谈起“消息机制”这个词,我们都会想到Windows的消息机制,系统将键盘鼠标的行为包装成一个Windows Message,然后系统主动将这些Windows Message派发给特定的窗口,实际上消息是被Post到特定窗口所在线程的消息队列,应用程序的消息循环再不断的从消息队列当中获取消息,然后再派发给特定窗口类的窗口过程来处理,在窗口过程中完成一次用户交互. 其实,WPF的底层也是基于Win

关于Flex事件机制的理解

优点:减少同一个UI树上对象监听器数量,从而带来性能优化. 1.FLEX 事件机制是分为三个阶段. 捕获---〉目标----〉冒泡 所谓捕获:即是寻找目标的过程,是目标的父节点.注:起点是Stage,终点也是Stage. 所谓目标:即是找到目标. 所谓冒泡:可以理解为捕获的返过程. 此为官方图解. 事件的派发: Flex中可以通过dispatchEvent()方法手工派发事件, 所有UIComponent的子类都可以调用此方法.   语法:   objectInstance.dispatchEv

关于事件机制的理解

最近终于把事件机制弄明白了.和大家分享一下. 下面是定义的事件: package { import flash.events.Event; public class NBEEvent extends Event { /** * 对 */ public static const RIGHT: String = "nbe_event_right"; public function NBEEvent(type: String, bubbles: Boolean = true, cancela

Atitit.事件机制 与 消息机制的联系与区别

1. 消息/事件机制是几乎所有开发语言都有的机制,在某些语言称之为消息(Event),有些地方称之为(Message).1 2. 发布/订阅模式1 3. 事件是侵入式设计,霸占你的主循环:消息是非侵入式设计,将主循环该怎样设计的自由留给用户.1 3.1. 事件越如 框架,消息相像类库2 3.2. 事件比消息封装的更高一层2 4. 消息队列和事件触发的区别,本质是没啥区别的2 5. 事件机制与消息机制2 1. 消息/事件机制是几乎所有开发语言都有的机制,在某些语言称之为消息(Event),有些地方

[转]as3事件流机制彻底理解

题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能喝很直观的理解.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说白了就是为了能让开发者能更好地控制事件调用顺序. addEventListener(type:String, listener:Function, useCapture:Boolean= false, priority:int= 0, useWeakReference:Boolean= false):

深入理解 Handler 消息机制

记得很多年前的一次面试中,面试官问了这么一个问题,你在项目中一般如何实现线程切换? 他的本意应该是考察 RxJava 的使用,只是我的答案是 Handler,他也就没有再追问下去了.在早期 Android 开发的荒芜时代,Handler 的确承担了项目中大部分的线程切换工作,通常包括子线程更新 UI 和消息传递.不光在我们自己的应用中,在整个 Android 体系中,Handler 消息机制也是极其重要的,不亚于 Binder 的地位. ActivityThread.java 中的内部类 H 就

(转载)Windows消息机制

文章出处:http://www.cnblogs.com/watsonyin/archive/2005/12/12/295536.html Windows消息机制 Windows操作系统最大的特点就是其图形化的操作界面,其图形化界面是建立在其消息处理机制这个基础之上的.如果不理解Windows消息处理机制,肯定无法深入的理解Windows编程.可惜很多程序员对Windows消息只是略有所闻,对其使用知之甚少,更不了解其内部实现原理,本文试着一步一步向大家披露我理解的Windows消息机制.可以说,