您的位置:首页 > Web前端

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
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息