BREW事件使用技巧: 避免事件冲突

来源:互联网 发布:雪糕 知乎 编辑:程序博客网 时间:2024/04/29 05:12

原则上,我是及其反感使用BREW事件机制来实现某些功能的。 理论上,除了BREW本身系统的自带事件机制外,我们在正常开发过程中,应该能不用事件就不用事件,能少用事件,就少用事件,只有万不得以时,才使用事件。 这是因为,使用事件机制,会导致耦合性加重。

 

但是,现实中,大家都为了简单,都随意的扩展自定义事件在应用间相互发送,使得事件被烂用,这真实比比皆是。

 

无奈,已经是事实,那在此事实面前,有何补救的方式那?? 个人认为,必须把握下面几点。 否则, 潜在的风险非常大。

 

 

1。 组件内事件

 

如果我们自己扩展了一个接口,且该接口支持_HandleEvent,那么,我们定义该接口能处理的事件,绝对不允许是自定义事件,即,EVT_USER开始的事件。 大家可以看看BREW,BUIW中但凡能处理事件的接口,他们定义的事件值,是不是均不在自定义事件范围那! 比如,Form,Widget,Container,ITextCtl,IMenu,Dialog等等。

 

那为什么必须不能定义为EVT_User范围的事件那。 这是应为, 组件的运行环境是不可预知的,所以,组件能收到的事件也不可预知,极有可能一个应用级的自定义事件被层层委派最后到组件的handleEvent中,如IForm_HandleEvent,那么,如果该组件本身的事件也定义在EVT_User范围中,那么是否就存在冲突了,把不属于自己的事件,当成自己的事件处理了,那么,轻则逻辑异常,重则直接Crash(事件参数的非法读写)。

 

 

一般组件都是OEM厂商开发的,那么,他们可以定义该事件的访问在OEM_Start 到 OEM_End, 或者是EVT_User之前的任何范围,理论上都是可以的,只需要自己保证不重复即可。

 

 

如果是第三方以动态的方式开发组件,那么如果该组件支持事件处理,且需要扩展新的事件,则可以考虑使用动态事件的方式,即IShell_RegisterEvent来预留事件, 不过感觉这样也比较麻烦。 到真不知道CP厂商们遇到这种情况,实际中是如何操作的。

 

 

2。应用自身内事件

 

BREW中的EVT_User事件本意就是应用发给应用自己的事件,这样才能保证不同应用之间不会冲突(因为EVT_User只会来自自己)。 所以,应用如果想发事件给自己,那么大胆的定义EVT_User事件把,不需要担心冲突

 

 

 

3。 应用间事件

 

一个应用(也可以不是应用环境下,如接口中)向多个别的应用发事件,这个要分为两种情况:

 

a。 目的应用是编译期已知的,通俗点说,就是ISHELL_Send/PostEvent中的clsid是已知的, 那么,事件允许定义为EVT_User范围。这是因为,目的应用在开发期就能理解该事件,做正常的处理。 当然多组不同的应用间事件以及应用内事件必须经过规划,以保证不冲突。

 

b。目的应用是编译器未定的,运行期动态获得的。 比如, 举一个场景, OEM厂商想实现特定界面按PWR KEY不退出的功能, 于是,采用的方案为,一旦PWR Key按下,OEM层获取当前前台应用的Stack,从顶部开始,依次发特定的事件给运行中的应用,如果应用返回FALSE,则被关闭,继续向下一个应用发事件。 如果返回TRUE,则不关闭,并停止事件的继续发送。   这样,大部分的应用对该事件不进行处理,则当按PWR时都被关闭。 而特定应用,特定界面,如电话中, 按Pwr健,应用将不被退出。

 

对于这样一种需求,那么,该特定事件,绝对不允许定义为EVT_User范围,因为接受该事件的应用处于被动接受方式,完全编译期不可知,只在运行期发生,那么,就极有可能造成与接收方应用内部的事件冲突,后果不堪设想!!   一个曾经真实的案例:

 

在某个第三方的动态应用中,按CLR健退出正常,但是按Pwr健不正常,会死机。 其原因就是,该应用内自定义了EVT_User事件,而运行手机平台中,当按Pwr健时,使用了向运行应用发送EVT_User事件询问是否允许被关闭的方案。 从而,造成了事件冲突,接收应用中对事件的参数读写方式按照自身定义的进行,直接导致非法访问(传入的事件的dwParm为NULL, 接收应用处理中,按照自己定义事件的dwParm方式处理,进行读写)

 

对于这种场景,必须使用非EVT_User范围的事件定义,或者动态事件。

原创粉丝点击