MTK中history机制小结
2011-05-13 17:12
806 查看
在MTK的程序开发中,必然会遇到history机制的问题。整体来讲,就是屏幕或应用界面的切换管理问题。在这个方面,MTK的设计是非常好的,在阅读前辈大牛们的总结后,结合自己项目开发中的一些认识,大致分析一下这一套机制。
为什么可以用这样的一个机制呢,不难想象,MTK只是单任务的系统,一个任务一旦开启(激活),那么另一个任务就要退出或到后台运行。这样就保证了任务之间的屏幕切换是单线串联的。想想,如果是多任务的系统,可能有多个任务在同时运行,不停在不同任务之间切换
1、EntryNewScreen
对于屏幕有两个非常基本的操作,一个进屏函数(Entry),一个及时退屏函数(exit)
每个应用都会用得的一个函数 EntryNewScreen 就是调用mmi_frm_entry_new_screen
mmi_frm_entry_new_screen
{
……
/*主要执行函数 ExecuteCurrExitHandler,保存历史记录和回调退出函数*/
ExecuteCurrExitHandler();
……
/*将新应用作为当前的应用*/
if ((new_exit_handler != NULL) || (new_entry_handler != NULL))
{
mmi_frm_set_generic_exit_handler(new_scrn_id, new_exit_handler, new_entry_handler);
}
……
<
4000
span style="font-size:small;">}
注意:只有当在调用mmi_frm_set_generic_exit_handler后,全局变量currExitScrnID、 curr_exit_handler、curr_entry_handle才表示当前应用。
void ExecuteCurrExitHandler_Ext(void)
{
……
/* 生成历史记录并保存 */
if (curr_entry_handler)
{
mmi_frm_generic_exit_scrn(currExitScrnID, curr_entry_handler);
}
/*回调当前退出窗口的退出函数*/
if (curr_exit_handler)
{
mmu_frm_execute_scrn_exit_handler = MMI_TRUE;
curr_exit_handler(curr_exit_scrn_arg_p);
mmu_frm_execute_scrn_exit_handler = MMI_FALSE;
}
……
}
对于mmi_frm_generic_exit_scrn()函数,其主要调用mmi_frm_add_history()
该函数应该深入研究一下
其中有一个全局变量IsBackHistory,这是一个标志位,标志是否是从GoBackHistory来调用该函数的,以此来决定是否执行后面的保存操作。为什么GoBackHistory会调用到这个地方呢?
其实很明了,EntryNewScreen 会在两种情况下被调用。
(1)主动进入一个应用时,产生前一应用的history,此时IsBackHistory为MMI_FALSE,于是就要将前一应用的加入history的堆栈中。
(2)通过GoBackHistory回退回来,但是不产生回退前应用的history。IsBackHistory 在GoBackHistory调用的mmi_frm_go_back_to_history_int函数中被赋值IsBackHistory = MMI_TRUE;
简单来说,IsBackHistory 就是判断 EntryNewScreen 是否要产生history。
2、history
首先分析一下history结构体
typedef struct _historyNode
{
U8 isTab;
/* 窗口号*/
U16 scrnID;
#ifdef __MMI_UI_SMALL_SCREEN_SUPPORT__
U16 isSmallScreen;
#endif
/* inputBuffer 保存当前编辑框 text 里的内容,比如说短信编辑时,来电话,返回时需要重新显示编辑
*/
U8 *inputBuffer; /* running text data */
/* guiBuffer 用于保存当前界面的一些状态信息。比如当前选中的item等等。
guiBuffer 就是一块内存,可以把它转化为任何结构体,保存信息。
*/
U8 *guiBuffer; /* this includes hilite item, input mode & etc.. */
MemAlloc mallcFuncPtr; /* keep the memory allocated function */
MemFree mfreeFuncPtr; /* keep the memory freed function */
mmi_history_node_status_enum status;
entry_func_ptr entryFuncPtr;
void *app_arg;
} historyNode;
static historyNode historyData[MAX_HISTORY]; /* array of history data */
先大概来理一下history栈的出入栈流程
1.入栈(EntryNewScreen):
(1) U8 EntryNewScreen(U16 newscrnID, FuncPtr newExitHandler, FuncPtr newEntryHandler, void *flag);
(2)void ExecuteCurrExitHandler (void);
(3)void ExecuteCurrExitHandler_Ext(void);
(4) void mmi_frm_generic_exit_scrn(U16 scrn_id, entry_func_ptr entry_func_ptr);
(5) MMI_BOOL mmi_frm_add_history(
U16 scrn_id, /* the screen id */
entry_func_ptr entryFuncPtr, /* the screen's entry function */
HistoryGetData getGuiFuncPtr, /* the function to get GUI data */
HistoryGetSize getInputBufSizeFuncPtr, /* the function to get input buffer size */
HistoryGetData getInputBufFuncPtr, /* the function to get input buffer */
MemAlloc mallocFuncPtr, /* the function to allocate memory */
MemFree mfreeFuncPtr, /* the function to free memory */
void* app_arg_p);
(6) static S16 increment(void);
2.出栈(GoBackHistory):
(1)void GoBackHistory(void);
(2)static U8 mmi_frm_go_back_to_history_int(U16 scrnid) //处理historyData
(3)static U8 decrement_current_history_index(void);
3、SetDelScrnIDCallbackHandler
SetDelScrnIDCallbackHandler函数很精妙,它设置一个回调函数,当这个screen id 被删除的时候,这个回调函数会被调用。当一个应用退出时,需要释放资源的话,最好设置这个函数,不然容易资源泄露。也许这个也可以在exit函数(该屏的退出函数,这样写实方便描述,以下皆同)中来进行操作,但是这样做,有可能需要做比较多的状态保存,来回恢复,更为复杂。因为此处的sreen id的删除是从history stack中删除,与exit函数从逻辑上有区别,执行exit函数时也许并没有从history stack中删除(反而可能是添加),当我返回时还要继续接着上次的进行操作。
(1)比如在照相机界面,来了一个短信,欲查看短信,按end键退出到idle,这时该screenid就从history stack中删除,这样就需要在被删除时释放资源。
(2)比如编辑短信时,闹钟响起,此时编辑短信的screen Id就加入到history stack中,如果在exit 中释放资源,就会要保存一些信息(如当前的编辑内容),而此时很可能关闭闹钟后就立即回到短信编辑界面,如果资源在exit释放了,那么此时就要进行恢复,显得很麻烦,所以在history stack中删除sreen id时来进行回调操作就显得较为方便了。
to be continued
ps:这是我在方案公司实习过程中学习mtk的简单小结,其中参考了很多技术大牛、MTK前辈们的一些总结博文,在此对他们表示崇敬和谢意。
参考文献及博文:
[1] http://blog.csdn.net/yanwuxufeng/archive/2010/08/15/5814655.aspx [2] http://blog.csdn.net/blogercn
[3] MTK专题集(讲述MTK各个重要功能模块).doc
为什么可以用这样的一个机制呢,不难想象,MTK只是单任务的系统,一个任务一旦开启(激活),那么另一个任务就要退出或到后台运行。这样就保证了任务之间的屏幕切换是单线串联的。想想,如果是多任务的系统,可能有多个任务在同时运行,不停在不同任务之间切换
1、EntryNewScreen
对于屏幕有两个非常基本的操作,一个进屏函数(Entry),一个及时退屏函数(exit)
每个应用都会用得的一个函数 EntryNewScreen 就是调用mmi_frm_entry_new_screen
mmi_frm_entry_new_screen
{
……
/*主要执行函数 ExecuteCurrExitHandler,保存历史记录和回调退出函数*/
ExecuteCurrExitHandler();
……
/*将新应用作为当前的应用*/
if ((new_exit_handler != NULL) || (new_entry_handler != NULL))
{
mmi_frm_set_generic_exit_handler(new_scrn_id, new_exit_handler, new_entry_handler);
}
……
<
4000
span style="font-size:small;">}
注意:只有当在调用mmi_frm_set_generic_exit_handler后,全局变量currExitScrnID、 curr_exit_handler、curr_entry_handle才表示当前应用。
void ExecuteCurrExitHandler_Ext(void)
{
……
/* 生成历史记录并保存 */
if (curr_entry_handler)
{
mmi_frm_generic_exit_scrn(currExitScrnID, curr_entry_handler);
}
/*回调当前退出窗口的退出函数*/
if (curr_exit_handler)
{
mmu_frm_execute_scrn_exit_handler = MMI_TRUE;
curr_exit_handler(curr_exit_scrn_arg_p);
mmu_frm_execute_scrn_exit_handler = MMI_FALSE;
}
……
}
对于mmi_frm_generic_exit_scrn()函数,其主要调用mmi_frm_add_history()
该函数应该深入研究一下
其中有一个全局变量IsBackHistory,这是一个标志位,标志是否是从GoBackHistory来调用该函数的,以此来决定是否执行后面的保存操作。为什么GoBackHistory会调用到这个地方呢?
其实很明了,EntryNewScreen 会在两种情况下被调用。
(1)主动进入一个应用时,产生前一应用的history,此时IsBackHistory为MMI_FALSE,于是就要将前一应用的加入history的堆栈中。
(2)通过GoBackHistory回退回来,但是不产生回退前应用的history。IsBackHistory 在GoBackHistory调用的mmi_frm_go_back_to_history_int函数中被赋值IsBackHistory = MMI_TRUE;
简单来说,IsBackHistory 就是判断 EntryNewScreen 是否要产生history。
2、history
首先分析一下history结构体
typedef struct _historyNode
{
U8 isTab;
/* 窗口号*/
U16 scrnID;
#ifdef __MMI_UI_SMALL_SCREEN_SUPPORT__
U16 isSmallScreen;
#endif
/* inputBuffer 保存当前编辑框 text 里的内容,比如说短信编辑时,来电话,返回时需要重新显示编辑
*/
U8 *inputBuffer; /* running text data */
/* guiBuffer 用于保存当前界面的一些状态信息。比如当前选中的item等等。
guiBuffer 就是一块内存,可以把它转化为任何结构体,保存信息。
*/
U8 *guiBuffer; /* this includes hilite item, input mode & etc.. */
MemAlloc mallcFuncPtr; /* keep the memory allocated function */
MemFree mfreeFuncPtr; /* keep the memory freed function */
mmi_history_node_status_enum status;
entry_func_ptr entryFuncPtr;
void *app_arg;
} historyNode;
static historyNode historyData[MAX_HISTORY]; /* array of history data */
先大概来理一下history栈的出入栈流程
1.入栈(EntryNewScreen):
(1) U8 EntryNewScreen(U16 newscrnID, FuncPtr newExitHandler, FuncPtr newEntryHandler, void *flag);
(2)void ExecuteCurrExitHandler (void);
(3)void ExecuteCurrExitHandler_Ext(void);
(4) void mmi_frm_generic_exit_scrn(U16 scrn_id, entry_func_ptr entry_func_ptr);
(5) MMI_BOOL mmi_frm_add_history(
U16 scrn_id, /* the screen id */
entry_func_ptr entryFuncPtr, /* the screen's entry function */
HistoryGetData getGuiFuncPtr, /* the function to get GUI data */
HistoryGetSize getInputBufSizeFuncPtr, /* the function to get input buffer size */
HistoryGetData getInputBufFuncPtr, /* the function to get input buffer */
MemAlloc mallocFuncPtr, /* the function to allocate memory */
MemFree mfreeFuncPtr, /* the function to free memory */
void* app_arg_p);
(6) static S16 increment(void);
2.出栈(GoBackHistory):
(1)void GoBackHistory(void);
(2)static U8 mmi_frm_go_back_to_history_int(U16 scrnid) //处理historyData
(3)static U8 decrement_current_history_index(void);
3、SetDelScrnIDCallbackHandler
SetDelScrnIDCallbackHandler函数很精妙,它设置一个回调函数,当这个screen id 被删除的时候,这个回调函数会被调用。当一个应用退出时,需要释放资源的话,最好设置这个函数,不然容易资源泄露。也许这个也可以在exit函数(该屏的退出函数,这样写实方便描述,以下皆同)中来进行操作,但是这样做,有可能需要做比较多的状态保存,来回恢复,更为复杂。因为此处的sreen id的删除是从history stack中删除,与exit函数从逻辑上有区别,执行exit函数时也许并没有从history stack中删除(反而可能是添加),当我返回时还要继续接着上次的进行操作。
(1)比如在照相机界面,来了一个短信,欲查看短信,按end键退出到idle,这时该screenid就从history stack中删除,这样就需要在被删除时释放资源。
(2)比如编辑短信时,闹钟响起,此时编辑短信的screen Id就加入到history stack中,如果在exit 中释放资源,就会要保存一些信息(如当前的编辑内容),而此时很可能关闭闹钟后就立即回到短信编辑界面,如果资源在exit释放了,那么此时就要进行恢复,显得很麻烦,所以在history stack中删除sreen id时来进行回调操作就显得较为方便了。
to be continued
ps:这是我在方案公司实习过程中学习mtk的简单小结,其中参考了很多技术大牛、MTK前辈们的一些总结博文,在此对他们表示崇敬和谢意。
参考文献及博文:
[1] http://blog.csdn.net/yanwuxufeng/archive/2010/08/15/5814655.aspx [2] http://blog.csdn.net/blogercn
[3] MTK专题集(讲述MTK各个重要功能模块).doc
相关文章推荐
- Flex程序开发心得小结
- 网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day
- css样式之区分input是按钮还是文本框的方法第1/4页
- 控制input的CSS但不影响CheckBox以及Radio的样式
- php中ob(Output Buffer 输出缓冲)函数使用方法
- js禁用和激活input表单的方法
- 让input不可点击的另一种方法
- javascript 面向对象编程 function是方法(函数)
- javascript 面向对象编程 function也是类
- IIS下PHP连接数据库提示mysql undefined function mysql_connect()
- input 高级限制级用法
- css美化input file按钮的代码方法
- 复制Input内容的js代码_支持所有浏览器,修正了Firefox3.5以上的问题
- JavaScript中Object和Function的关系小结
- Javascript 使用function定义构造函数
- javascript Object与Function使用
- input 日期选择功能的javascript代码
- 利用JavaScript更改input中radio和checkbox样式
- javascript下function声明一些小结
- 常用的javascript function代码