在TouchGFX中,Callback模板的描述放在Callback.hpp文件中,在此定义了两组模板:GenericCallback与 Callback模板。
GenericCallback模板组
GenericCallback为Callback模板的模板基类。在GenericCallback模板中,定义了两个接口函数:isValid与execute;其中isValid是来检测Callback是否被初始化过,而execute函数用于调用实际要执行的函数。GenericCallback模板组总共定义了4个模板,模板之间的差别在于execute函数的参数个数不同,4个模板分别对应execute函数带有0个参数,1个参数,2个参数与3个参数。本文中仅列出execute带一个参数的情况。
下面是execute函数带1个参数的GenericCallback模板:
Callback模板组
Callback模板由GenericCallback派生而来。Callback模板组也有4个模板,分别对应于包含不同参数个数execute函数的GenericCallback模板,继承关系如下图:
下面是execute函数带1个参数的Callback模板:
在Callback结构中定义了两个私有的成员指针,pobject为dest_type类型对象的指针,pmemfun_1为dest_type对象的成员函数指针,是指向dest_type类型的成员函数。这样当Callback结构初始化好了以后,再调用execute函数时,就是直接调用了dest_type类型对象的成员函数pmemfun_1。
在使用Callback模板时,根据模板的特性,C++编译器会自动选择最准确的模板匹配,来生成对应的模板类或模板函数。因此在使用Callback模板时,可以使用不同的类型参数个数来匹配使用不同的模板。
页面切换 - pendingScreenTransitionCallback
在TouchGFX启动过程中会初始化MVPApplication对象,在MVPApplication类中定义了一个成员pendingScreenTransitionCallback,它是GenericCallback<>*类型的指针,并初始化为0;
TouchGFX会调用handlePendingScreenTransition函数进行页面切换,最终调用evaluatePendingScreenTransition函数,在此函数中会用isValid()函数来检查Callback是否已经初始化;如果初始化了,就调用execute函数 (因为Callback为GenericCallback<>*类型,因此execute函数不带参数) 。
具体的页面切换过程(进入第一个screen):
在TouchGFX初始化过程中,会初始化FrontendApplication对象app,在此对象的基类中包含一个transitionCallback成员,其类型为:
touchgfx::Callback<FrontendApplicationBase> transitionCallback
在进入第一个Screen时,会调用app.gotoScreen1ScreenNoTransition(),在此函数中,会将pendingScreenTransitionCallback设置为指向transitionCallback的指针,最终由TouchGFX框架调用execute函数,执行makeTransition完成页面的切换。
// 初始化FrontendApplicationBase::transitionCallback,transitionCallback的私有成员初始化:
// pobject赋值为this(指向FrontendApplicationBase)
// pmemfun_1赋值为 &FrontendApplication::gotoScreen1ScreenNoTransitionImpl
//execute函数内实际执行的函数(pobject->*pmemfun_1)(),即为如下函数:
按键响应 - flexButtonCallback
在TouchGFX designer中创建一个Flex Button,并设置interaction后,会在MainViewBase类中创建两个私有成员:
//按键响应函数,实现用户的动作响应
void flexButtonCallbackHandler(const touchgfx::AbstractButtonContainer& src)
//Callback对象
touchgfx::Callback<MainViewBase, const touchgfx::AbstractButtonContainer&> flexButtonCallback
以及一个按键成员(在designer中通过Add Style添加了Image与Text属性),例如flexButton1:
touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::ClickButtonTrigger > > flexButton1;
在MainViewBase的构造函数中,会初始化flexButtonCallback成员,并且调用flexButton1->setAction函数,设置此按键的AbstractButton::action为flexButtonCallback,
MainViewBase::MainViewBase():flexButtonCallback(this, MainViewBase::flexButtonCallbackHandler)
其中:
flexButtonCallback的pobject成员初始化为this(指向MainViewBase的指针)
flexButtonCallback的pmemfun_1成员初始化为&MainViewBase::flexButtonCallbackHandler
由于flexButtonCallback的类型是
struct Callback<dest_type, T1, void, void> : public GenericCallback<T1>
因此flexButtonCallback的execute函数带有一个参数,参数类型为const touchgfx::AbstractButtonContainer&,最终此参数会传递给flexButtonCallbackHandler函数。
在程序运行时,点击按键后,TouchGFX框架会捕获此事件,并在AbstractButton::handleClickEvent函数中调用action->execute(*this)函数,最终即执行了flexButtonCallbackHandler函数,实现了用户的动作响应。