Symbian學(xué)習(xí)筆記(3)——應(yīng)用程序框架
不管是哪一種模板,它們共同的部分是入口函數(shù)、Application和Document。即以下三個(gè)文件是所有工程都具有的:
1)有一個(gè)與工程同名的cpp文件,它只提供了兩個(gè)全局函數(shù),是程序執(zhí)行的入口,負(fù)責(zé)創(chuàng)造Application。這個(gè)文件我們不用管它。
2)有一個(gè)以工程名+Application命名的類,派生于CAknApplication,它負(fù)責(zé)創(chuàng)建文檔類并提供應(yīng)用的UID。一般情況下它也不需要我們操心,但是因?yàn)樗峁┝艘粋€(gè)函數(shù)OpenIniFileLC,如果我們需要在啟動(dòng)程序時(shí)加載ini文件中的配置,可以重載它。
3)有一個(gè)以工程名+Document命名的類,派生于CAknDocument,它負(fù)責(zé)創(chuàng)建Ui類,同樣一般情況我們不管它,但是它也提供了一個(gè)函數(shù)OpenFileL,如果需要加載普通文件,也可以重載它。
下面來(lái)看看兩種模板的不同點(diǎn)吧。
一. 基于CCoeControl的常規(guī)模式
這種模式的特點(diǎn)是一個(gè)AppUi類并且對(duì)應(yīng)一個(gè)Container類。
它在上述三個(gè)文件以外,還有下面兩個(gè)文件:
4)有一個(gè)以工程名+AppUi命名的類,派生于CAknAppUi,它主要的工作是負(fù)責(zé)用戶接口(所謂的UI)并且創(chuàng)建Container類,所以它是我們關(guān)注的重點(diǎn)之一。
它最重要的成員函數(shù)是HandleCommandL,這個(gè)函數(shù)來(lái)自于CEikAppUi類,負(fù)責(zé)處理各種命名/事件。
有兩個(gè)函數(shù)DynInitMenuBarL和DynInitMenuPaneL,如果需要?jiǎng)討B(tài)更改菜單的項(xiàng)目,可以重載它們。
HandleKeyEventL函數(shù)則可以在需要自己處理鍵盤事件時(shí)重載一下。
此外,這個(gè)AppUi還提供一些比較常用的函數(shù),比如:
Document() 可以獲取Document對(duì)象指針。
Application() 可以獲取Application對(duì)象指針。
StatusPane() 可以獲取狀態(tài)欄的指針。
Cba() 可以獲取控制欄的指針。
5)有一個(gè)以工程名+Container命名的類,派生于CCoeControl,它負(fù)責(zé)內(nèi)容的展示,也是我們關(guān)注的重點(diǎn)。
如果需要在界面上增加控件類類的東西,都是在這個(gè)類中實(shí)現(xiàn),總的來(lái)說(shuō),它負(fù)責(zé)所有與界面展示相關(guān)的東西。
它有一個(gè)Draw函數(shù),但是如果我們是通過(guò)控件來(lái)展示信息,則這個(gè)函數(shù)里的代碼似乎與我們關(guān)系不大,除非我們的界面完全是靠畫出來(lái)的。
另兩個(gè)函數(shù)ComponentControl和CountComponentControls分別獲取控件與獲取控件個(gè)數(shù),在依賴于控件展示的GUI應(yīng)用中則更為重要。
因?yàn)樗鼘?shí)現(xiàn)了接口MCoeControlObserver,所以函數(shù)HandleControlEventL也需要實(shí)現(xiàn)一下。
利用它的成員iCoeEnv可以取到AppUi類的指針,不過(guò)需要強(qiáng)制轉(zhuǎn)型一下,如:STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->...
二. 基于CAknView的MVC模式
這種模式的特點(diǎn)是在AppUi類與Container類之間增加一個(gè)AppView的類,即一個(gè)AppUi對(duì)象,N個(gè)AppView和N個(gè)Container。
除了公共的三個(gè)文件以外,它包括的文件有:
4) 有一個(gè)以工程名+AppUi命名的類,派生于CAknViewAppUi類,其實(shí)也是間接派生于CAknAppUi類,它的工作職責(zé)與常規(guī)模式中的AppUi類也基本相同。
***的區(qū)別在于它不是直接創(chuàng)建Container類,而是創(chuàng)建AppView類,并且是創(chuàng)建多個(gè)AppView類。同時(shí)它還需要負(fù)責(zé)將創(chuàng)建的view加入視圖棧里AddViewL。
CleanupStack::PushL( view1 );
view1->ConstructL();
AddViewL( view1 ); // transfer ownership to CAknViewAppUi
CleanupStack::Pop(); // view1
CiMusicViewFavt* view2 = new (ELeave) CiMusicViewFavt;
CleanupStack::PushL( view2 );
view2->ConstructL();
AddViewL( view2 ); // transfer ownership to CAknViewAppUi
CleanupStack::Pop(); // view2
CiMusicViewWeb* view3 = new (ELeave) CiMusicViewWeb;
CleanupStack::PushL( view3 );
view3->ConstructL();
AddViewL( view3 ); // transfer ownership to CAknViewAppUi
CleanupStack::Pop(); // view3
this->ActivateLocalViewL(KViewMusicId);
5)有多個(gè)以工程名+View命名的類,派生于CAknView類。它負(fù)責(zé)分擔(dān)AppUi部分事件的處理,所以,它也有HandleCommandL函數(shù)。
此外,它的DoActivateL和DoDeactivate兩個(gè)函數(shù)在當(dāng)前視圖激活或失活時(shí)被調(diào)用,需要重載一下。
在激活時(shí),需要?jiǎng)?chuàng)建視圖對(duì)應(yīng)的Container類,并且調(diào)用Container的SetMopParent為自己,還要在上層的AppUi中將這個(gè)Container加入棧中。一般代碼如下:
iContainer->SetMopParent(this);
iContainer->ConstructL( AppUi()->ApplicationRect() );
iContainer->listType=type;
AppUi()->AddToStackL( *this, iContainer );
注意,它的AppUi()可以得到它的上層的AppUi對(duì)象指針。
失活時(shí)則正好相反,需要
...{
AppUi()->RemoveFromViewStack( *this, iContainer );
}
delete iContainer;
iContainer = NULL;
6)有多個(gè)以工程名+Container命名的類,派生于CCoeControl并實(shí)現(xiàn)接口MCoeControlObserver,所以它的行為與常規(guī)模式中的Container類似。
這種模式可以有效地組織應(yīng)用程序,根據(jù)應(yīng)用的多個(gè)功能界面切割成數(shù)個(gè)模塊(視圖)。由多個(gè)AppView來(lái)分擔(dān)AppUi中的事件處理,負(fù)責(zé)自己這個(gè)視圖下的具體行為與顯示。
各個(gè)視圖之間的切換也很簡(jiǎn)單:
STATIC_CAST(CiMusicAppUi*,iCoeEnv->AppUi())->ActivateLocalViewL(KViewMusicId);
[補(bǔ)充]
三 比較兩種模式
有些教材還提出過(guò)對(duì)話框模式,但是我覺得那似乎不太實(shí)用,也沒注意過(guò)它的結(jié)構(gòu)組成。
對(duì)比上述兩種架構(gòu)模板,很顯然,第二種基于視圖的模板應(yīng)該更有實(shí)用性一點(diǎn),除非程序?qū)嵲诤?jiǎn)單。
不過(guò),這里的“視圖”很容易讓人產(chǎn)生誤解。一般我們說(shuō)MVC的時(shí)候,模型-視圖-控制器,但是這里的AppView其實(shí)對(duì)應(yīng)的控制器,而Container對(duì)應(yīng)的則是視圖。
所以在新的SDK里,***種模板中由向?qū)傻墓こ讨性从贑CoeControl的類名改成了AppView,對(duì)應(yīng)繼承于CAknAppUi控制器的類名叫AppUi。因?yàn)槲覜]有看到多視圖的工程生成的代碼,如果這樣的話,估計(jì)也應(yīng)該對(duì)應(yīng)的改一下吧。
【編輯推薦】