1、 History stack
在上篇文章分析到history机制在利用顺序栈来保存历史信息,说白了就是一个数组加一个指向栈顶的标记。
static historyNode historyData[MAX_HISTORY]; /* array of history data */
static S16 currHistoryIndex = -1;//指向当前
static S16 topHistoryIndex = -1;//指向栈顶
入栈时调用
static S16 increment(void)
{
++currHistoryIndex;
++topHistoryIndex;
return currHistoryIndex;
}
出栈时调用
static void decrement_current_history_index(void)
{ while (currHistoryIndex >= 0 && (historyData[currHistoryIndex].status != MMI_HIST_NODE_NORMAL))
{
currHistoryIndex--;
}
}
那么在使用手机时,我们会发现,当进行某些操作时,就没有返回操作,如按END key,在大部分情况下,在按键回到待机界面。即此时的history stack已经清空。可以跟踪代码发现end key 返回待机界面时,会调用DisplayIdleScreen(),该函数中有一个很重要的函数
ExecuteRootMainHistoryScreen(),返回到history栈底的screen,也就是idlescreen。
2、 GetCategoryHistory
关键点:存入 historyData[].guiBuffer
(1)定义
在文件wgui_categories_util.c中定义了
U8 *(*GetCategoryHistory) (U8 *buffer) = dummy_get_history;
该函数指针就一个全局变量,保存了获取当前屏的模板历史的函数的地址。
(2)赋值
一般在void ShowCategoryXXXScreen()函数中对其进行赋值。或在dm_setup_category_functions函数中进行赋值。
例如:
GetCategoryHistory = dm_get_category_history;
GetCategoryHistory = GetCategory57History;
其中函数U8 *dm_get_category_history(U8 *history_buffer)是在drawmanger中定义的一个获取模板信息的函数。针对不同的模板信息,调用的函数进行处理。
如:
case DM_LIST1:
{
get_list_menu_category_history((U16) p_dm_data->s32CatId, history_buffer);
break;
}
(3)调用
当退出屏并且需要保存到history stack中时进行调用,且调用的方式是多样的。此处我只分析了两种情况。可能是在特定的退出函数exitXXXscreen,或者通用的退出屏函数mmi_frm_generic_exit_scrn中,都会调用 GetCategoryHistory(h.guiBuffer);
<1>、先单独获得guibuffer然后传入到AddHistory中。
如:GetCategoryHistory(h.guiBuffer);
AddNHistory(h, inputBufferSize);
<2>将GetCategoryHistory 传入到添加history的函数中,在该函数中获取guibuffer。
如:mmi_frm_generic_exit_scrn()函数中
mmi_frm_add_history(scrn_id, entry_func_ptr, GetCategoryHistory, NULL, NULL, NULL, NULL, curr_exit_scrn_arg_p);
然后在mmi_frm_add_history函数中
getGuiFuncPtr(historyData[topHistoryIndex].guiBuffer);此处的getGuiFuncPtr也就是传入的GetCategoryHistory函数指针
3、 关于GetCurrGuiBuffer
问题:为何在EntryNewScreen()后就调用GetCurrGuiBuffer?那能获得什么信息?
关键点:获取historyData[].guiBuffer
guiBuffer = GetCurrGuiBuffer(SCR_ID_XXX);
函数U8 *GetCurrGuiBuffer(U16 scrnid)获得当前屏的GUI buffer,该buffer保存了该屏的一些关于高亮选中的信息。当应用利用此函数从MMI history数据库中获取gui buffer的指针时,并且在该屏激活时间中,保持其生命周期。如果scrnid并不是当前的屏,则返回空指针。
其实该函数就是要获取我们前面第2点GetCategoryHistory中所讲到的保存到历史堆栈的guibuffer,花了那么大的力气去保存,现如今总算也要拿出来用用了。
这个逻辑其实在上一篇文章中已经讲到,即EntryNewScreen 会在两种情况下被调用,这个进入某个应用的函数EntryXXX也会在第一次进入应用或者GoBackHistory时调用。
<1>、如果是GoBackHistory时调用,则需要恢复上次退出屏时的一些历史信息,如选中了某个选项,高亮了某个菜单等等。那这些信息在退屏时进行了保存,那进屏时就要将其重新读出。
<2>、如果是第一次进入该应用,则在history stack中没有该屏的信息,则return NULL;
获取到guibuffer后,则毫不留情的传入到showXXXcategory()中,无限的跟踪下去,总会发现在某个函数中将guibuffer赋值到当前屏的信息中了。
如:set_list_menu_category_history(history_ID, history_buffer);
嗨,这个函数原来跟上面举例的get_list_menu_category_history是一对。
写了这么些,虽然分条列点,但也觉得凌乱,不妨综合上面信息来简单画一个草图。
正所谓一阴一阳之谓道,一来一去,一开一合,如此巧妙。
PS:此日志花了大半天的时间去阅读代码并整理,在整理过程中自己的思路也慢慢清晰了。但也正所谓新手入门,错误难免,还请各位帮忙指正。