2. TouchGFX基础回顾
在进入多页面架构设计之前,有必要把 TouchGFX 的运行时骨架重新梳理一遍。很多页面跳转、数据刷新、动画卡顿的问题,根源并不在页面本身,而在于对引擎调度机制和 MVP 职责边界的理解偏差。本节围绕 TouchGFX 引擎、MVP 模式、View、Presenter、Model、Screen 六个核心概念展开,帮助你在后续多页面设计中做出正确的结构决策。
一、TouchGFX 引擎:驱动整个 UI 的“心跳”
TouchGFX 引擎是运行在目标板上的核心框架,它负责把应用逻辑与 LCD 刷新、触摸事件、DMA 传输连接起来。引擎并不直接绘制像素,而是通过抽象层调用硬件加速(如 LTDC、DMA2D、GPU2D)完成渲染。其关键职责包括:
- 事件循环:持续采集触摸、按键与系统 tick,分发给当前活动 Screen。
- 渲染调度:按帧率驱动重绘,只刷新发生变化的区域(dirty region),降低带宽占用。
- 时间基准:为动画、定时器、过渡效果提供统一的 tick 源。
- 内存管理:管理帧缓冲、位图缓存与动态内存池。
引擎的调度节奏决定了多页面切换的流畅度。若在 Presenter 中执行阻塞操作,会直接拖慢整个事件循环,表现为触摸无响应或动画掉帧。
二、MVP 模式:职责分离的设计基石
TouchGFX 采用 MVP(Model-View-Presenter)模式组织代码,其核心目的是把“界面长什么样”和“业务怎么处理”彻底分开。三者关系如下:
- Model:持有应用数据与业务逻辑,不感知任何 UI 控件。
- View:由 Designer 生成的界面类,负责控件布局、绘制与用户输入采集。
- Presenter:连接 View 与 Model,响应 View 的事件、更新 Model,并把数据变化回写到 View。
三、核心对象与协作关系
下面这张图展示了 TouchGFX 引擎、MVP 三层以及 Screen 之间的静态结构与数据流向。注意 View 与 Presenter 是双向绑定,而 Model 只与 Presenter 交互。
四、Screen:多页面架构的基本单元
Screen 是 TouchGFX 中可被激活、切换和销毁的界面单元。一个 Screen 通常由一对 View 与 Presenter 组成,并可能关联一个 Model 或共享全局 Model。Screen 的生命周期由引擎管理,典型阶段包括:
- 构造:创建 View 与 Presenter 对象,建立绑定关系。
- setupScreen:初始化控件、注册回调、加载初始数据。
- 激活:成为当前显示页面,开始接收触摸事件与 tick。
- tearDownScreen:离开页面时释放资源、停止定时器。
五、核心对象职责对照
| 对象 | 核心职责 | 不应做的事 | 多页面中的角色 |
|---|---|---|---|
| 引擎 | 事件循环、渲染调度、时间基准 | 承载业务逻辑 | 统一驱动所有 Screen |
| View | 控件布局、绘制、输入采集 | 直接访问 Model | 每个 Screen 独立一份 |
| Presenter | 事件响应、数据转换、调用 Model | 直接操作硬件寄存器 | 页面逻辑的集中点 |
| Model | 业务数据与逻辑 | 引用 View 或控件 | 可跨页面共享 |
| Screen | View + Presenter 的组合单元 | 承担全局状态 | 页面切换的基本单位 |
六、典型代码结构
在 TouchGFX Designer 生成的基础上,Presenter 通常通过 setView 与 View 绑定,并在 activate 中完成数据初始化。下面是一个简化示例:
class MainPresenter : public touchgfx::Presenter {
public:
MainPresenter(MainView& v) : view(v) {}
virtual void activate() {
// 从 Model 读取数据并刷新界面
view.setTemperature(model.getTemperature());
view.setStatusText(model.getStatusText());
}
void onStartButtonClicked() {
model.startMeasurement();
view.setStatusText("测量中...");
}
private:
MainView& view;
SystemModel& model = SystemModel::getInstance();
};
可以看到,Presenter 只做“翻译”和“调度”:把 View 的点击翻译成 Model 的操作,再把 Model 的状态翻译成 View 的显示。View 本身不关心温度从哪里来,Model 也不关心温度显示在哪个控件上。
七、常见误区与复盘
- 误区一:在 View 中直接调用 Model。这会让界面与业务耦合,后续换屏或复用逻辑时改动面巨大。
- 误区二:把全局状态塞进某个 Screen。Screen 会被销毁重建,全局数据应放在共享 Model 或单例中。
- 误区三:在 Presenter 中做阻塞延时。会卡住引擎事件循环,导致触摸丢失和动画停顿。
- 误区四:每个页面各建一个 Model。多页面之间数据不同步,容易出现“返回后数据没更新”的问题。
理解引擎的调度方式、MVP 的职责边界以及 Screen 的生命周期,是后续设计页面跳转、数据共享和过渡动画的前提。把这些基础对象的关系理清,多页面架构才不会退化成“一堆互相引用的界面类”。