声明式 UI 简介

本简介描述了 Flutter 使用的声明式风格与许多其他 UI 框架使用的命令式风格之间的概念差异。

为什么是声明式 UI?

从 Win32 到 Web 再到 Android 和 iOS 的框架通常使用命令式 UI 编程风格。这可能是你最熟悉的风格,即手动构建一个功能齐全的 UI 实体,例如 UIView 或等效项,然后在 UI 更改时使用方法和设置器对其进行更改。

为了减轻开发人员在编程如何转换到各种 UI 状态方面的负担,Flutter 相反允许开发人员描述当前的 UI 状态,并将转换留给框架。

然而,这需要稍微改变一下如何操作 UI 的思路。

如何在声明式框架中更改 UI

考虑以下简化示例

View B (contained by view A) morphs from containing two views, c1 and c2, to containing only view c3

在命令式风格中,你通常会转到 ViewB 的所有者并使用选择器或 findViewById 或类似方法检索实例 b,并对其调用更改(并隐式地使其无效)。例如

// Imperative style
b.setColor(red)
b.clearChildren()
ViewC c3 = new ViewC(...)
b.add(c3)

你可能还需要在 ViewB 的构造函数中复制此配置,因为 UI 的真实来源可能比实例 b 本身存在的时间长。

在声明式风格中,视图配置(例如 Flutter 的小部件)是不可变的,并且只是轻量级的“蓝图”。要更改 UI,小部件会触发自身重新构建(在 Flutter 中最常见的是对 StatefulWidgets 调用 setState()),并构建一个新的 Widget 子树。

// Declarative style
return ViewB(
  color: red,
  child: const ViewC(),
);

在这里,当 UI 更改时,Flutter 不是更改旧实例 b,而是构建新的 Widget 实例。该框架在幕后使用 RenderObjects 管理传统 UI 对象的许多职责(例如维护布局状态)。RenderObjects 在帧之间持久存在,而 Flutter 的轻量级 Widget 告诉框架在状态之间更改 RenderObjects。Flutter 框架处理其余部分。