使用手机的经验告诉我们,手机页面需要频繁的进行迁移时,实现页面迁移的方案和其效率的高低对于内存很小的手机来说都是至关重要的。
3.1 基本BREW页面迁移方案
对于一个BREW开发的页面迁移的程序,基本的解决反感就是可以自行设置一组宏分别代表页面的不同状态,每个状态再对应一个BREW的事件处理过程,在每个事件处理中,通过对按键的判断来调用不同的应用函数,如页面的新建、打开、重画、删除、和键盘事件的相应函数,调用后再进行页面的迁移。BREW可以利用这种调用的机制,实现通过按键完成函数和函数之间不断的调用过程。
该类方案的具体处理过程在手机处理按键的caseEVT_KEY中:根据不同的页面的宏标识ID执行不同页面的handleevent事件函数。
例如:
//根据不同的窗口,调用不同文件中的事件处理程序
switch(pMe->activeView) {//判断当前的活动页面
case IDW_GAME://如果是游戏页面,则执行游戏页面对应的事件处理程序
return GameWnd_HandleEvent(&pMe->game, eCode, wParam, dwParam);
case IDW_MAINMENU: //如果是主页面,则执行主页面对应的事件处理程序
return MainMenuWnd_HandleEvent(&pMe->mainMenu, eCode, wParam, dwParam);
……
default:break ;
}
该种方案的特点是较为利于理解,但是使用时容易出错,不宜调试。
3.2 类多态的BREW页面迁移方案
经过上述分析可以看出,手机中的页面迁移问题与C++中实现的多态效果十分相似,也就是完成一个窗体接口类的实现, 该接口类能完成绘制屏幕和接收客户键盘输入的功能,对于客户的相同输入, 不同的窗体结构应该能体现出不同的行为。如果可以利用C语言这种非面向对象的语言写出面向对象的程序,将有利于提高程序的重用性、模块化功能以及健壮性。
BREW平台中的宏QINTERFACE,GET_PVTBL,DECLARE_VTBL可以用来完成这种效果。其本质就是在基类的层次上定义一个“空函数集”,通过该空函数集实现一个抽象的,虚拟的,通用的接口层,可以在运行时根据对象的实际类型动态地调用派生类的那些“具体”函数,简言之,就是同一个接口函数,根据具体的对象,调用具体的函数。
使用时首先通过Qinterface定义了一个包含VTBL(虚函数表)的接口,在运行时,根据具体传入的对象类型调用了具体派生接口的“具体”函数。如:#define IWINDOW_Enable(p)GET_PVTBL(p, IWindow)->Enable(p, TRUE)这里p是IWINDOW指针类型。用户调用IWINDOW_Enable(p)时,虽然此时传入的是IWINDOW类型指针,但是其实质是派生的具体接口类型,所以最终调用到的就是属于它(派生具体接口)的具体接口函数了。
以下代码用于完成一个满足上述要求的页面迁移过程。
typedef struct _IWindowIWindow;
QINTERFACE(IWindow)
{
void (*Enable)(IWindow * po, boolean bEnable);
void (*Redraw)(IWindow * po);
boolean(*HandleEvent)(IWindow * po, AEEEvent eCode, uint16 wParam, uint32 dwParam);
……
};
#define IWINDOW_Enable(p) GET_PVTBL(p, IWindow)->Enable(p, TRUE)
…
#define IWINDOW_Redraw(p) GET_PVTBL(p, IWindow)->Redraw(p)
#define IWINDOW_HandleEvent(p, e, w, dw) GET_PVTBL(p, IWindow)->HandleEvent(p, e, w, dw)
……
#define INHERIT_CWindow(iname)
DECLARE_VTBL(iname)
IShell * m_pIShell;
IDisplay * m_pIDisplay;
struct CWindow
{
INHERIT_CWindow(IWindow);
};
具体实现的功能如图1所示: