# 1. 简介

# 1.1 AWTK

AWTK 全称 Toolkit AnyWhere,是 ZLG 基于 C 语言开发的开源 GUI 引擎,详情可前往 AWTK官网 (opens new window) 查看。源码可前往 GitHub仓库 (opens new window) 下载。

在阅读本文之前,首先需要对 AWTK 有基本用法有所了解,具体可以参阅《AWTK开发实践》。

# 1.2 MVVM 模式

在开发应用程序时,要把用户界面和业务逻辑分离开来,这是每个程序员都知道的常识。分离用户界面和业务逻辑有几个重要的好处:

  1. 有利于隔离变化。当界面发生变化时,减少业务逻辑代码的改动,降低开发的成本和周期。
  2. 有利于自动测试。分离用户界面和业务逻辑是提高代码可测试性的重要手段,让编写单元测试程序成为可能。
  3. 有利于分工合作。界面和业务逻辑的分离有助于设计师和程序员分工协作,减少矛盾,提高开发效率。

目前最常用的分离用户界面和业务逻辑模式就是 MVVM 模式,它把系统分成模型(Model)、视图(View)和视图模型(ViewModel)这三部分,明确的把用户界面和业务逻辑分离开来,如下图所示:

图1.1 MVVM 模式
图1.1 MVVM 模式

# 1.2.1 模型(Model)

模型(Model)就是业务逻辑。我们经常说面向对象的设计和建模,所建立的模型就是这里的模型,是对现实世界中业务逻辑的抽象。

面向对象的建模,就是要找到业务逻辑中有哪些类以及这些类之间的关系。类描述了对象的属性和行为,类是设计时的概念,对象是运行时的概念。对象通常就是业务实体,Model 包含一个或多个业务实体。

需要注意的是,Model 并不单纯指的是数据,它是对象的集合,对象是即有数据又有行为的,光有数据没有行为,就无法让对象之间协作,无法共同完成业务逻辑。

# 1.2.2 视图(View)

视图(View)就是用户与软件交互的界面,对于 GUI 应用程序来讲,就是窗口和对话框,以及上面的各种控件。视图应该说是为用户提供了一个界面,让用户可以观察和操作模型。

# 1.2.3 视图模型(ViewModel)

在 MVVM 模式中,View 与 Model 之间通过一些规则建立联系,也就是数据绑定命令绑定

  • View 通过数据绑定在界面上显示 Model 中的指定数据,当 Model 中的数据更新时又会通知 View 进行更新。
  • View 通过命令绑定来执行 Model 中的指定操作,即用户在界面上触发事件时(比如点击按钮),执行 Model 业务实体对象中的函数(行为)。

根据数据绑定命令绑定规则实现 View 和 Model 交互的中间层就是视图模型(ViewModel),它作为二者沟通的桥梁,当用户在 View 上修改数据时将其自动同步到 Model 中,当 Model 中的数据有变化时自动更新到 View 上,并且通过命令绑定实现 View 中触发事件执行 Model 层函数的功能。

MVVM 模式实现的核心就是一条条数据绑定和命令绑定的规则,对规则的处理和解释成了 MVVM 框架或公用库,可以在多个项目中共享,即下文所说的 AWTK-MVVM (opens new window)

# 1. ViewModel 与 View 的关系

由于 ViewModel 在 View 眼中仍然是模型,它与 View 没有直接关系,因此是可以为 ViewModel 编写单元测试的。

# 2. ViewModel 与 Model 的关系

虽然在 View 眼中 ViewModel 仍然是模型,但它其实与 Model 并不相同,之所以要引入 ViewModel,主要原因如下:

  • Model 中的数据有时并不适合直接显示在 View 上。比如出版日期在 Model 中可能是是整数,直接显示出来,用户就看不懂,需要转换成人类可以理解的字符串。
  • Model 中的一个数据项可能以多种形式呈现在 View 上。比如出版日期除了直接显示外,也可能给最近出版的书显示一个新书标志。
  • View 中的输入数据和 Model 中的存储数据,它们的格式有时可能不同。比如出版日期,View 上输入的格式和 Model 里存储的格式就不一样。
  • View 需要 ViewModel 提供数据校验规则来判断视图上的输入是否合法。
  • 有些数据是有依赖关系的,这些处理可以交给 ViewModel 去做。比如在输入收货地址时,选择省份时,城市列表跟着变化。
  • 有些状态不属于业务逻辑,但是需要保存下来。如为了支持撤销操作,需要保存命令历史记录。
  • 在 C/C++ 等静态语言中,没有办法通过函数的名称去调用对象的成员函数,也没有办法通过属性的名称去访问对象的成员变量。ViewModel 需要提供一种机制来实现这些功能,否则绑定规则就没法实现。

可以看出 ViewModel 既是 View 和 Model 之间的粘合剂,又是润滑剂。

# 1.2.4 MVVM 模式的优缺点

MVVM 模式有以下优点:

  1. 强制分离用户界面和业务逻辑。MVVM 中不需要编写界面相关的代码,自然没有办法让用户界面和业务逻辑耦合到一起。
  2. 界面描述文件和程序代码之间具有更松的耦合。MVVM 模式采用了面向意图的编程,界面上表现的只是一种意图,至于在程序中,谁去实现,怎么实现,甚至有没有实现,界面都是不关心的,所以界面和代码之间值的耦合是很松的。
  3. 不需要学习 GUI 的 API。通过数据绑定和命令绑定建立视图和模型之间的联系。用声明式的规则取代命令式的代码,不需要写界面相关的代码,所以不需要学习 GUI 的 API。

除了以上优点,MVVM 模式还存在以下缺点,在开发应用前需要根据项目实际情况判断是否适合采用 MVVM 模式:

  1. 内存问题。据说 WPF(Windows Persentation Foundation) 内存开销很大,即使在 PC 上也大得让人无法忍受(常有人借此来反对MVVM)。WEB 前端流行的 MVVM 框架,像 React 和 Vue.js 等,采用虚拟 DOM 的方式,内存需求可能有大幅度增加。
  2. 性能问题。MVVM 通常的做法是,模型有变化时会刷新整个界面。如果采用虚拟 DOM 的方式,还需要重新构建一个虚拟 DOM,与原来的虚拟 DOM 比较,性能开销就更大了。
  3. 调试问题。数据绑定使得 Bug 很难被调试,它会将 Bug 转移到其他位置,比如看到界面显示异常,有可能是 View 有问题,也可能是 Model 有问题,或者二者都有问题。

更多关于 MVVM 模式的相关介绍详见:awtk-mvvm/docs/8.intro.md (opens new window)

# 1.3 AWTK-MVVM

AWTK-MVVM (opens new window) 是一套用 C 语言开发的,专门为嵌入式平台优化的 MVVM 框架。它实现了数据绑定、命令绑定和窗口导航等基本功能,使用 AWTK-MVVM 开发应用程序,无需学习 AWTK 本身的 API,只需学习绑定规则和模型的实现方式即可。

与其它 MVVM 框架相比,AWTK-MVVM 特点有:

  • 代码小。

    • 核心代码:约3000行。
    • AWTK 相关代码:约700行。
    • JerryScript 相关代码(可选):约1700行。
  • 性能高。核心代码用 C 语言开发,其性能与直接使用 AWTK 差别不大。

  • 内存开销小。

    • 一条绑定规则约占150字节。一个窗口上若有10条绑定规则,内存占用也就1.5K。
    • 列表中的绑定规则可以共享,额外增加的内存开销,比例也是很小的。
  • 隔离更彻底。在 AWTK-MVVM 中,界面和绑定规则在 XML 中描述,开发应用程序时只需要开发模型(也就是业务逻辑)即可。除非通过特殊手段,开发者没有机会直接去访问视图。

  • 易调试。

    • 提供 ViewModel 的框架生成工具,避免手写代码造成的错误。
    • 增加了各种异常处理的日志信息。
    • 提供大量的示例程序以供参考。
    • 开放源码,调试方便。
  • 支持多语言开发。

    • 目前支持 C 语言和 JS 语言。
    • 以后会根据需要支持新的编程语言。

AWTK-MVVM (opens new window) 的内存需求评估请参考:awtk-mvvm/docs/memory_req.md (opens new window)

# 1.4 AWTK Designer中的MVVM项目

AWTK Designer 是专门用来制作 AWTK 应用程序 UI 界面的实用工具。只要通过拖拽和点击就可以完成复杂的界面设计,操作简单;可以随时预览效果,所见即所得,下载地址和使用方法详见《AWTK Designer用户手册》。

AWTK Designer 专业版中内置了 AWTK-MVVM (opens new window),可以新建并编辑 MVVM 项目,降低 MVVM 项目的开发难度,提高开发效率。目前支持以下两类 MVVM 项目,它们都使用 XML 描述 UI,如下图所示:

图1.2 AWTK Designer中的MVVM项目
图1.2 AWTK Designer中的MVVM项目
  • MVVM-C 项目:使用 AWTK-MVVM 框架,基于 C 语言开发应用程序的工程项目,该类项目的 Model 层和 ViewModel 层均采用 C 语言实现。
  • MVVM-JS 项目:使用 AWTK-MVVM 框架和 JerryScript 引擎,基于 JS 语言开发应用程序的工程项目,该类项目的 Model 层和 ViewModel 层均采用 JS 语言实现。

在后面的章节中,我们将详解介绍如何使用 AWTK Designer 制作 MVVM-C 项目和 MVVM-JS 项目。