touchgfx的工作机制

touchgfx的工作机制

一.MVP软件架构

MVP的全称为Model-View-Presenter

Model: 就是数据部分,在整个touchgfx应用中,只有一个Model类实例对象,它为所有的Screen屏幕界面服务,可以理解成是一个全局变量区,同时它还负责和后端系统通信

View: 就是UI界面部分,对应于View类,在整个touchgfx应用中,可以存在多个View实例对象,一个View实例对象其实就是一个Screen屏幕界面

Presenter: 就是项目的业务逻辑部分,相当于是一个主持人,负责在Model和View之间进行数据中转

注: 每一个Screen屏幕界面,都会有一个专有的View类和专有的Presenter类与之对应,但是Model类是所有屏幕界面共有的

二.View类

1.构造函数: 主要是做一些成员变量的初始化

2.setupScreen : 主要是做一些UI控件的属性初始化

3.tearDownScreen: 做一些资源释放

4.虚构函数: 做一些资源释放

上面四个函数也可以说是一个Screen屏幕界面的生命周期,由从上到下的顺序被系统调用,而且都只会被调用一次

三.Model类

1.构造函数: 主要是做一些成员变量的初始化

2.Tick函数: 每隔一个tick周期就会被调用一次,而一个tick周期其实就是一个屏幕刷新周期,取决于你的LCD像素时钟,一般在20ms左右,在这里主要负责轮询后端系统的事件

四.Presenter类

1.构造函数

2.activate

3.deactivate

五.内存管理机制

这里的内存指的是微处理器内部的ram

touchgfx中的控件对象的内存分配全部都是在内部ram中的,而且都是分配在几个私有的大数组中

cpp 复制代码
Block stBlocks[NUMBER_OF_ELEMENTS];

因此touchgfx的内存分配是在程序编译时就完成了的,而不是在程序运行时动态分配的,

因此内存消耗的大小是确定可控的,不会出现运行时的内存泄露问题

内存管理的细节由FontendHeap单例类(在TouchGFX\gui\include\gui\common目录下)来描述,总内存消耗由以下几部分构成:

touchgfx::Partition< CombinedPresenterTypes, 1 > presenters;

touchgfx::Partition< CombinedViewTypes, 1 > views;

touchgfx::Partition< CombinedTransitionTypes, 1 > transitions;//屏幕切换动画

Model model;

FrontendApplication app;

举例:

1.presenters所分配的内存空间大小等于界面中内存消耗最大的那一个Presenter,而不是所有的Presenter内存消耗的总和,然后所有的Presenter共享同一个presenters内存区域,即分时复用

2.views所分配的内存空间大小等于界面中内存消耗最大的那一个View,而不是所有的View内存消耗的总和,然后所有的View共享同一个views内存区域,即分时复用

(五)启动流程

(1)void touchgfx_init()

cpp 复制代码
void touchgfx_init()
{
    //挂载图片数据库
    Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
    //挂载文本服务类
    TypedText::registerTexts(&texts);
    //设置语言
    Texts::setLanguage(0);
    //设置字体提供器
    FontManager::setFontProvider(&fontProvider);
    //创建内存管理
    FrontendHeap& heap = FrontendHeap::getInstance();
    /*
     * we need to obtain the reference above to initialize the frontend heap.
     */
    //避免警告
    (void)heap;

    /*
     * Initialize TouchGFX
     */
    hal.initialize();
}

(2)

cpp 复制代码
static FrontendHeap& getInstance()
{
    static FrontendHeap instance;
    return instance;
}

(3)跳转到启动界面

cpp 复制代码
FrontendHeap() : FrontendHeapBase(presenters, views, transitions, app),
                     app(model, *this)
    {
        gotoStartScreen(app);
    }

(4)

cpp 复制代码
virtual void gotoStartScreen(FrontendApplication& app)
{
    app.gotostartScreenScreenNoTransition();
}

(5)设置回调函数,此时是没有进行界面跳转的

cpp 复制代码
void FrontendApplicationBase::gotostartScreenScreenNoTransition()
{
    transitionCallback = touchgfx::Callback<FrontendApplicationBase>(this, &FrontendApplicationBase::gotostartScreenScreenNoTransitionImpl);
    pendingScreenTransitionCallback = &transitionCallback;
}

(6)这个地方才是真正的界面跳转

cpp 复制代码
void FrontendApplicationBase::gotostartScreenScreenNoTransitionImpl()
{
    touchgfx::makeTransition<startScreenView, startScreenPresenter, touchgfx::NoTransition, Model >(&currentScreen, &currentPresenter, frontendHeap, &currentTransition, &model);
}

(7)预跳转

cpp 复制代码
template <class ScreenType, class PresenterType, class TransType, class ModelType>
PresenterType* makeTransition(Screen** currentScreen, Presenter** currentPresenter, MVPHeap& heap, Transition** currentTrans, ModelType* model)
{
    assert(sizeof(ScreenType) <= heap.screenStorage.element_size() && "View allocation error: Check that all views are added to FrontendHeap::ViewTypes");
    assert(sizeof(PresenterType) <= heap.presenterStorage.element_size() && "Presenter allocation error: Check that all presenters are added to FrontendHeap::PresenterTypes");
    assert(sizeof(TransType) <= heap.transitionStorage.element_size() && "Transition allocation error: Check that all transitions are added to FrontendHeap::TransitionTypes");
//跳转之前的操作,主要把当前界面的资源进行释放(View类,Presenter类,Transition类)
    prepareTransition(currentScreen, currentPresenter, currentTrans);
//placement 在一个地址上分配内存,不会重新分配内存空间
    TransType* newTransition = new (&heap.transitionStorage.at<TransType>(0)) TransType;
    ScreenType* newScreen = new (&heap.screenStorage.at<ScreenType>(0)) ScreenType;
    PresenterType* newPresenter = new (&heap.presenterStorage.at<PresenterType>(0)) PresenterType(*newScreen);
   //绑定
    *currentTrans = newTransition;
    *currentPresenter = newPresenter;
    *currentScreen = newScreen;
    model->bind(newPresenter);
    newPresenter->bind(model);
    newScreen->bind(*newPresenter);

    finalizeTransition((Screen*)newScreen, (Presenter*)newPresenter, (Transition*)newTransition);

    return newPresenter;
}

(8)跳转

cpp 复制代码
FORCE_INLINE_FUNCTION static void finalizeTransition(Screen* newScreen, Presenter* newPresenter, Transition* newTransition)
{
    newScreen->setupScreen();
    newPresenter->activate();
    newScreen->bindTransition(*newTransition);
    newTransition->init();
    newTransition->invalidate();
}
相关推荐
猫猫的小茶馆9 分钟前
【STM32】预分频因子(Prescaler)和重装载值(Reload Value)
c语言·stm32·单片机·嵌入式硬件·mcu·51单片机
riveting42 分钟前
明远智睿H618:开启多场景智慧生活新时代
人工智能·嵌入式硬件·智能硬件·lga封装·3506
三万棵雪松2 小时前
【STM32HAL-第1讲 基础篇-单片机简介】
stm32·单片机·嵌入式硬件
玉树临风江流儿2 小时前
炸鸡派-基础测试例程
单片机·嵌入式硬件
智者知已应修善业4 小时前
【51单片机用数码管显示流水灯的种类是按钮控制数码管加一和流水灯】2022-6-14
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
智商偏低10 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen11 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
白鱼不小白13 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D14 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术17 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件