Skip to content

flutter_application_architecture

理解 Flutter 的架构是构建高效且易于维护的应用的关键。本章探讨了支撑 Flutter 开发的核心概念。

Flutter 中最基本的概念是:万物皆组件(Everything is a Widget)。 组件是 Flutter 应用用户界面的基本构建块。把它们想象成乐高积木:你组合更小、更专业的积木(组件)来创建更大、更复杂的结构(屏幕或整个应用)。

即使应用本身也是一个组件,通常从 MaterialApp 或 CupertinoApp 开始。UI 是以组件树的形式构建的。每个组件描述了用户界面的一部分,例如按钮 (ElevatedButton)、文本 (Text)、内边距 (Padding) 或布局结构 (Column, Row)。

这种组合模型非常强大。你通过组合现有组件来构建自定义 UI 组件,而不是继承大型基类。例如,一个自定义卡片可能由一个 Card 组件组成,该组件包含一个 Column,Column 中又包含一个 Image 和一些 Text 组件。

考虑一下基本的 ‘Hello World’ 应用结构:

  • MyApp (你的根组件 Root Widget): 通常是一个 StatelessWidget 或 StatefulWidget。
  • 它构建一个 MaterialApp (或 CupertinoApp),该组件提供核心应用功能(主题、导航)。
  • MaterialApp 的 home 属性指定主屏幕。
  • 主屏幕通常是一个 Scaffold 组件,它提供标准的应用程序布局结构(AppBar、body、FloatingActionButton)。
  • Scaffold 的 appBar 可能是一个 AppBar 组件。
  • Scaffold 的 body 可以是一个 Center 组件,用于使其子组件居中。
  • Center 组件的 child 可以是一个 Text 组件,显示 ‘Hello World’。

这种层次结构演示了组件如何相互嵌套以创建最终的 UI。

Flutter 不仅使用组件来表示 UI 元素(如按钮),还用于布局(定位和尺寸)。不像 Android 中的 XML 那样使用单独的布局文件,你直接在 Dart 代码中使用布局组件,如 Row、Column、Stack、Padding、Center、Expanded 等。

  • Row 和 Column: 沿直线(水平或垂直)排列子组件。
  • Stack: 将子组件叠加在一起。
  • Container: 一个多功能的盒子,用于样式设置(颜色、边框、形状)、尺寸调整、内边距和外边距。
  • Padding: 在其子组件周围添加空间。
  • Center: 使其子组件居中。
  • Expanded 和 Flexible: 控制子组件如何在 Row 或 Column 中共享空间。

你就像组合任何其他组件一样组合这些布局组件,以实现复杂的设计。

Flutter 组件可以通过手势响应用户输入。GestureDetector 组件是一个非可视组件,用于在其子组件上检测各种交互,如点击、拖动、缩放等。

你将想要使其具有交互性的组件包装在 GestureDetector 中,并为你想要处理的手势提供回调函数(如 onTap, onDoubleTap, onLongPress, onPanUpdate)。

GestureDetector(
onTap: () {
print('Widget tapped!'); // 组件被点击了!
// 执行点击操作
},
child: Container(
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: Text('Tap Me'), // 点我
),
)

许多内置组件,如 ElevatedButton 或 InkWell,为了方便起见内置了手势检测功能。

管理状态:无状态 (Stateless) 与有状态 (Stateful) 组件

Section titled “管理状态:无状态 (Stateless) 与有状态 (Stateful) 组件”

Flutter 中的组件要么是无状态的(Stateless),要么是有状态的(Stateful)。

  • StatelessWidget: 描述 UI 的一部分,该部分仅依赖于其自身的配置(通过构造函数传入)和 BuildContext。它没有任何随时间变化的内部状态。示例:Text、Icon、Padding。它们一旦创建就是不可变的。
  • StatefulWidget: 描述 UI 的一部分,该部分可以根据用户交互或数据更新动态变化。它有一个关联的 State 对象,该对象持有可变状态并定义 build 方法。当状态改变时(通过调用 setState()),框架会重建该组件以反映新状态。示例:Checkbox、TextField、自定义动画。

Flutter 的框架是响应式的(reactive)。当 StatefulWidget 的状态通过 setState() 改变时,Flutter 只会高效地重建组件树中必要的部分。它会将上次构建的组件配置与新的进行比较,并最小化地更新底层的渲染对象(render objects)。

虽然 setState 对于管理本地组件状态至关重要,但大型应用通常需要更复杂的“状态管理”(State Management)解决方案(如 Provider、Riverpod、BLoC)来处理需要在组件树不同部分之间共享的状态。这在状态管理章节中有所介绍。

在 Dart 框架之下是主要用 C++ 编写的 Flutter Engine。这个引擎负责核心任务:

  • 渲染(Rendering): 使用 Skia 图形库直接在平台(Android/iOS/Web/Desktop)提供的画布上绘制 UI。这避免了依赖原生 OEM 组件,让 Flutter 可以控制每个像素,确保 UI 在不同平台上的表现一致。
  • 平台通道(Platform Channels): 通过消息传递与平台特定的服务(如相机、位置、传感器)通信。
  • Dart 运行时(Dart Runtime): 执行应用程序的 Dart 代码。

构建过程将组件树转换为元素树,然后元素树配置底层的渲染对象。这些渲染对象知道如何将自身绘制到画布上。当状态改变时,Flutter 会高效地更新相关的渲染对象,并仅重新绘制必要的部分。

Flutter 采用分层设计,允许开发者在不同的抽象级别工作:

  • 框架层(Framework,Dart): 包含 Material 和 Cupertino 组件库、核心组件系统、渲染层、动画、手势等。大多数开发者主要在这个层面工作。
  • 引擎层(Engine,C++): 提供 Flutter 核心 API 的底层实现,包括 Skia、Dart 运行时和文本渲染。
  • 嵌入层(Embedder,平台特定): 一个平台特定层,将 Flutter 引擎与宿主操作系统集成。它处理事件循环、平台表面、可访问性、输入以及平台通道通信。

这种分层设计促进了关注点分离,并允许系统的不同部分独立更新或替换。

关键的架构要点:

  • Flutter UI 通过组合不可变的**组件(Widgets)**来构建。
  • 布局也由组件处理(Row、Column、Stack 等)。
  • GestureDetector(或内置处理程序)管理用户交互。
  • 状态管理要么在 StatefulWidget 内部使用 setState 进行本地管理,要么使用专门的状态管理解决方案来处理共享状态。
  • Flutter 通过 Skia 直接绘制到画布,确保高性能和一致性。
  • 架构是分层的,分离了框架层、引擎层和平台嵌入层。

理解这些概念为你构建健壮且高性能的 Flutter 应用奠定了坚实的基础。