天天看點

事件驅動模型

版權聲明:本文為半吊子子全棧工匠(wireless_com,同公衆号)原創文章,未經允許不得轉載。 https://blog.csdn.net/wireless_com/article/details/6470752

BREW應用程式的模型是基于一個事件驅動的協作式多任務模型。事件處理機制的核心問題是程式應該隻處理需要的事件,對于不需要處理的事件,需要傳回給系統處理。應用在加載之後可以通過 HandleEvent()函數接收所有輸入的事件,然後會通過傳回TRUE(已處理)或FALSE(未處理)訓示是否處理事件。AEE層存在一個全局的事件隊列,所有的事件都存儲在該隊列中,如果隊列中的事件在分發後處理完畢或者無人處理,該事件将被從事件隊列中删除。

BREW中的事件主要有三類:系統事件,預定義的事件和自定義的事件。系統事件的事件代碼範圍為0~7,即從EVT_APP_START 到 EVT_APP_BROWSE_FILE。預定義事件的事件代碼範圍是0x0008-0x4fff,即BREW AEE 層和OEM層預定義或者預留的事件。自定義的事件是指 BREW應用可以自定義自己的事件,自定義事件應該不小于EVT_USER(0x5000)。BREW應用可以發送任何事件給應用自身,或者發給在同一程序中的其他應用。如果發送事件給不同程序的應用(主要是針對BREW 4.X及以上版本),這時需要特殊的應用權限。

BREW環境要求及時地處理事件。簡而言之,如果應用執行處理事件HandleEvent()調用後沒能在合适的時間傳回,AEE可能就會關閉應用以保護裝置相應其他請求。有些操作,比如說從網絡套接字中讀取資料,也許耗時過長,無法在一次調用事件處理器内完成。這時就采用回調機制,以便在操作完成之後通知該應用。

4.3.2.1事件處理器

AEE執行環境調用BREW 應用自身的事件處理器來傳遞關于一系列事件的消息。有過windows程式設計經曆的讀者都會清楚這種機制,Windows下消息處理機制:當在互動中進行一個操作(信号,輸入,等等),windows将産生相應的事件,通過window的事件分發機制,相應的視窗或者應用得到該事件,進而觸發相應的事件處理器進行處理。BREW中事件處理機制與其相似,即BREW環境捕捉到事件後,分發到相應的應用或者控件,由應用或者控件的事件處理器進行處理。

以下是BREW中事件處理器接口的示例:

       boolean MyApp_HandleEvent(IApplet * pIApp,

       AEEEvent eCode,

       uint16 wParam,

       uint32 wParam)

在該示例中,變量pIApp實際上指明了應用的結構,也就是AEEApplet的一個指針。許多應用将其結構定義為AEEApplet的超集,而pIApp也能指向該結構。

eCode變量是說明應用接收的事件類型,如EVT_APP_START、EVT_KEY和EVT_ALARM等典型事件。

wParam和dwParam參數是依據接收的事件而定義的短資料和長資料值。這些值取決于事件本身,根據事件自身來定義。對于某些事件,短資料和長資料字段中都包含事件資料;而對于另一些事件,長短字段中僅有一個字段,甚至沒有字段。兩個資料字段均不包含資料的事件有EVT_APP_START、EVT_APP_STOP、EVT_APP_SUSPEND和EVT_APP_RESUME。兩個資料字段中都包含資料的典型事件有EVT_DIALOG_START和EVT_COMMAND。僅在短資料字段中包含資料的典型事件有EVT_ALARM,僅在長資料字段中包含資料的典型事件有EVT_NET_STATUS和EVT_CTL_CHANGING。

按鍵事件作為EVT_KEY 事件發送給應用。短資料字段包含主鍵代碼;比如說如果使用者按下按鍵符合“2”,就包含AVK_2這一主鍵代碼。AVK_2的值由AEEVCodes.h頭檔案定義。

在Emulator中,與按鍵符号相對應的主鍵代碼由裝置配置檔案确定,也可經由裝置配置器進行修改。在手機上,主鍵代碼由裝置廠商決定。

4.3.2.2事件處理的提示

執行應用時,僅考慮處理應用可能需要處理的事件。許多事件可以被忽略。舉例來說,如果執行一個遊戲應用時,僅需使用上下左右箭頭鍵,則可忽略接收到的0-9按鍵事件。

但是如果接收到關鍵事件,則無論應用處于何種狀态都不能忽略。如EVT_START、 EVT_STOP、EVT_SUSPEND和EVT_RESUME等系統事件就是在任何情況下都會影響應用的例子,是以不能忽略。需要特别注意的是,無論應用給定狀态如何,必須接收所有的關鍵事件。某些事件在應用特别訓示需要此類通知時才會發送。應用必須為這些通知事件注冊,可以在MIF編輯器中指定MIF檔案的通知事件注冊,或者使用ISHELL_RegisterNotify()進行動态注冊。

作為一個約定,應用在處理EVT_START配置設定的任何資料,在處理EVT_STOP時都應該釋放出去。但是,在AEEClsCreateInstance()中配置設定的記憶體資料,一般必須通過FreeAppData()機制來釋放。

4.3.2.3事件分發與代理

當控件激活時,事件應該傳遞到激活的控件,使控件進行自我更新,又叫做事件代理。例如,如果菜單控件處于激活狀态,應該将事件傳遞到IMENUCTL_HandleEvent();如果文本控件處于激活上,應傳遞到ITEXTCTL_HandleEvent(),然後控件就會采取相應的操作。以菜單控件來說,它就會改變被選項目,重新繪制菜單。

正如事件處理函數将TRUE或FALSE傳回AEE執行環境那樣,控件傳回TRUE或FALSE則表示它們處理的事件。每個控件類型隻會處理必要的事件。标準菜單控件隻處理“上”、“下”和其他部分關鍵事件,而軟鍵菜單控件則處理“左“、“右”和其他關鍵事件。如果一個控件從發放的事件中傳回的是TRUE,應用就可以早一點從事件處理函數中退出來,但還可以執行額外的處理。如果一個控件從發放的事件中傳回的是FALSE,應用一般應該繼續處理該事件。如果該控件接收的是從事件處理器傳回的FALSE,BREW就要執行預設的處理。

當使用者按下“選擇”鍵進行選擇時,菜單控件使用EVT_COMMAND來通知應用。在這種情況下,一個來自“選擇”鍵下放的EVT_KEY按鍵事件就由菜單控件處理。此外,對于菜單控件任何視圖更新,菜單控件将EVT_COMMAND事件發回給應用。事實上,所有控件類型都能提供代理機制。

AEE   Shell

My App

IMenuCtl

所有的事件

按鍵事件

Ture /False

圖 4-7: BREW中的事件分發示例

       事件的分發代理機制非常靈活,你可以在消息循環中按照你的需要自由處理(圖。

使用者按下某一個鍵

與該鍵相關的事件被傳送

給您的事件處理函數

可以将它交給

IMENUCTL_HandleEvent()

可以選擇先處理它

也可以再次處理它

圖 4-8: BREW中的事件代理機制

       BREW下的消息處理機制與Windows下的消息處理機制的差別在于:BREW的體系結構采用了COM方式,即具有面向對象的類層次結構,進而其具體的事件處理機制也是作為各個接口外露的接口函數的形式被運用。一個應用本質上來說就是一個執行個體化的IAPPLET類,是以這樣就統一了所有在應用中運用的事件處理機制都是各個接口外露接口函數的說法。具體而言,這些事件處理器還是有差別的,主要是IAPPLET_HandleEvent和其他接口的HandleEvent的差別。

       IAPPLET_Handleevent是通過在AEEClsCreateInstance中的AEEApplet_New函數被注冊執行個體化的,AEEApplet_New函數執行個體化應用同時也通過傳入USERAPP_HandleEvent參數執行個體化了IAPPLET_Handleevent。

       除了IAPPLET具有handleevent外,所有的繼承IControl的接口也具有事件處理函數,允許處理事件。這些各種具體的IControl_handleEvent有兩種方式被調用。一種是在應用的handleevent中由開發者顯式的調用,如:

switch (eCode)

{

    case EVT_APP_START:                            

     return(TRUE);

    case EVT_APP_STOP:    

……….

        Case EVT_KEY:

IMENU_Handleevent….

ItextCtl_Handleevent….

}

另一種是當這些控件包含于對話框中,且處于聚焦狀态時,這些事件處理函數的觸發是隐式的,是由AEE機制自動觸發的,無需在代碼中顯式的調用這些handleevent。 IDialog接口沒有外露的handleevent接口函數,但是允許通過IDialog_seteventhandle來注冊一個該對話框的事件處理函數。需要注意的是該事件處理函數是何時被觸發的:一旦當一個對話框處于激活時,AEE層将會把所有的事件直接發往該對話框,該對話框會自動的調用處于焦點控件的handleevent來處理該事件,隻有當該控件沒有處理該事件時,對話框注冊的事件處理函數才會被調用。

當BREW運作後,首先作業系統中的ui 任務會捕捉到各種事件,此時ui 任務通過aee_dispatch将事件分發至BREW環境中。BREW環境再通過aee_sentevent具體分發事件至目的地,在兩種不同的情況下将走不同的流程。

       如果目前沒有激活的對話框,則緊接着IAPPLET_Handleevent被BREW自動調用來處理事件,而此時調用的IAPPLET_Handleevent其實就是使用者注冊的app_handleevent。進而實作了允許使用者的應用捕捉到事件并處理的機制。在使用者的app_handleevent中,使用者可以将事件繼續下發,比如通過調用IMENU_handleevent等将事件下發給各種控件處理。

如果目前有激活的對話框,則基于對話框的事件被BREW自動調用,進而使得事件被對話框最先截獲,而對話框之後的處理是檢查包含的控件中哪個處于焦點,并将事件下發給它的handleevent來處理,同時根據其傳回值來判斷其是否已經處理了該事件,當其傳回False後,對話框将該事件繼續轉發至該對話框注冊的handleevent(如果有的話),如果該handleevent仍然傳回false,BREW繼續将該事件轉發至app_handleevent。這種機制使得當以對話框方式來建立應用時,各種事件被自動的處理,進而簡化了代碼量,但也使得事件流程更加晦澀,使用者的應用程式不能直接的控制它。

本文來自CSDN部落格,轉載請标明出處:

http://blog.csdn.net/wireless_com/archive/2009/07/21/4365612.aspx