架构概览
About 2246 wordsAbout 7 min
Flutter前端开发UI人机交互
2025-01-09
Flutter 是一个跨平台的 UI 工具集,它的设计初衷,就是允许在各种操作系统上复用同样的代码,例如 iOS 和 Android,同时让应用程序可以直接与底层平台服务进行交互。
在开发中,Flutter 应用会在一个 VM(程序虚拟机)中运行
,从而可以在保留状态且无需重新编译的情况下,热重载
相关的更新。
对于发行版 (release) ,Flutter 应用程序会直接编译为 机器代码(Intel x64 或 ARM 指令集)
,或者针对 Web 平台的 JavaScript。
Flutter 的框架代码是开源的,遵循 BSD 开源协议。
架构
Flutter 被设计为一个可扩展的分层系统。它可以被看作是各个独立的组件的系列合集,上层组件各自依赖下层组件。组件无法越权访问更底层的内容,并且框架层中的各个部分都是可选且可替代的。
嵌入层 采用了适合当前平台的语言编写,例如 Android 使用的是 Java 和 C++, iOS 和 macOS 使用的是 Objective-C 和 Objective-C++,Windows 和 Linux 使用的是 C++。 Flutter 代码可以通过嵌入层,以模块方式集成到现有的应用中,也可以作为应用的主体。
Flutter引擎 毫无疑问是 Flutter 的核心,它主要使用 C++ 编写,并提供了 Flutter 应用所需的原语。引擎将底层 C++ 代码包装成 Dart 代码,通过 dart:ui 暴露给 Flutter 框架层。
Flutter框架层 以 Dart 语言编写的现代响应式框架 ,它包括由一系列层组成的一组丰富的平台,布局和基础库。从下层到上层,依次有:
- 基础的 foundational 类及一些基层之上的构建块服务,如 animation、 painting 和 gestures,它们可以提供上层常用的抽象。
- 渲染层 用于提供操作布局的抽象。有了渲染层,你可以构建一棵可渲染对象的树。在你动态更新这些对象时,渲染树也会自动根据你的变更来更新布局。
- widget 层 是一种组合的抽象。每一个渲染层中的渲染对象,都在 widgets 层中有一个对应的类。此外,widgets 层让你可以自由组合你需要复用的各种类。响应式编程模型就在该层级中被引入。
- Material 和 Cupertino 库提供了全面的 widgets 层的原语组合,这套组合分别实现了 Material 和 iOS 设计规范。
Flutter 框架相对较小,因为一些开发者可能会使用到的更高层级的功能已经被拆分到不同的软件包中,使用 Dart 和 Flutter 的核心库实现,其中包括平台插件,例如 camera 和 webview;与平台无关的功能,例如 characters、 http 和 animations。还有一些软件包来自于更为宽泛的生态系统中,例如 应用内支付、 Apple 认证 和 Lottie 动画。
应用剖析
通过flutter create命令创建的应用的结构如图所示
Dart 应用
- 将 widget 合成预期的 UI。
- 实现对应的业务
- 由应用开发者进行管理。
框架(源代码)
- 提供了上层的 API 封装,用于构建高质量的应用(例如 widget、触摸检测、手势竞技、无障碍和文字输入)。
- 将应用的 widget 树构建至一个 Scene 中。
引擎(源代码)
- 将已经合成的 Scene 进行栅格化。
- 对 Flutter 的核心 API 进行了底层封装(例如图形图像、文本布局和 Dart 的运行时)
- 将其功能通过 dart:ui API 暴露给框架。
- 使用 嵌入层 API 与平台进行整合。
嵌入层(源代码)
- 协调底层操作系统的服务,例如渲染层、无障碍和输入。
- 管理事件循环体系。
- 将特定平台的 API 暴露给应用集成嵌入层。
运行器
- 将嵌入层暴露的平台 API 合成为目标平台可以运行的应用包。
- 部分内容由 flutter create 生成,由应用开发者进行管理。
Flutter 中的状态管理
Flutter 提供了多种状态管理方案,包括:
- Provider: 官方推荐的状态管理库,简单、灵活,并与 Flutter 密切集成。
- Redux: 一种受 React 启发的状态管理库,适合需要全局管理复杂状态的应用。
Flutter 与原生代码的交互
Flutter 通过 平台通道(Platform Channels) 实现与原生代码的交互。例如,如果你需要使用设备的原生功能(如相机、蓝牙或传感器),可以通过平台通道调用 Android 和 iOS 原生代码。
Flutter 中的 Widget 和 Element 有什么区别?
Widget
是 Flutter 中 UI 的构建块。它是一个不可变的描述符,定义了 UI 的外观和行为。每个 Widget 都有一个对应的 Element 对象,它是 Widget 树中与实际渲染和更新相关的部分。Element
代表了 Widget 在屏幕上的实际实例,Widget 可能会发生变化,但 Element 通常是存在的,直到 Widget 被销毁。Note
在 Flutter 中,每当界面状态发生变化(比如用户交互或状态刷新),Flutter 会调用 build 方法重新生成新的 Widget 树。这些新的 Widget 替代了旧的 Widget,但不会直接影响对应的 Element。 虽然 Widget 会变化,Element 通常会被复用,并且只在必要时才会被销毁或替换(例如某些节点从树中被移除)。它通过维护与新旧 Widget 的引用关系,避免了每次重建树时都重新创建所有 Element 和对应的渲染对象,从而优化了性能。
什么是 StatefulWidget 和 StatelessWidget?
- StatelessWidget:无状态组件,其状态在创建时确定,并且在生命周期中不再变化。
- StatefulWidget:有状态组件,可以在其生命周期中动态改变状态。当状态变化时,Flutter 会重新构建该 Widget。
Flutter 中如何处理布局?
Flutter 使用一种声明式布局方式。布局是通过嵌套 Widgets 来实现的,常见的布局 Widgets 包括 Container、Column、Row、Stack、Flex 等。
Flutter 中如何进行数据绑定?
Flutter 不像传统的框架一样有自动数据绑定,而是通过控制状态的更新来改变 UI。常见的状态管理方法包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 等。
在 Flutter 中,UI 的更新由开发者明确控制,主要通过 状态的变化 来驱动。Flutter 不会主动监听状态的变化,而是需要开发者明确地调用方法(如 setState)来通知框架更新 UI。
setState
简单的局部状态管理 InheritedWidget
需要在父组件和子组件之间共享状态 Provider
更简单的全局或跨组件状态管理 Bloc(Business Logic Component)
复杂项目,需要分离业务逻辑和 UI
Flutter 如何与原生代码进行交互?
使用 平台通道(Platform Channels),Flutter 通过平台通道与 Android 和 iOS 的原生代码进行通信。具体是指你可以通过 MethodChannel 和 EventChannel 来调用原生方法和接收原生事件。
解释 Flutter 的 Future 和 Stream 是什么
Future
是 Dart 中用来处理异步操作的重要工具。它表示一个可能在未来某个时间完成的操作,并提供了机制来处理操作完成后的结果或错误Stream
是一个表示异步事件序列的接口,允许你监听一系列的事件,并对每个事件作出响应,适用于事件流(例如 WebSocket 或实时数据)。包括singleStream(单订阅)和broadcastStream(广播)
如何在 Flutter 中实现异步操作
在 Flutter 中,异步操作通过 async/await 进行管理。可以使用 Future 和 Stream 来处理异步数据。
什么是 Hot Reload 和 Hot Restart
Hot Reload
:能够快速重新加载代码更改并保持应用的状态,常用于 UI 和小范围代码的修改Hot Restart
:完全重新启动应用,并重新初始化状态,适用于更广泛的代码变更
如何在 Flutter 中使用持久化存储?
shared_preferences
插件来存储简单的数据sqflite
插件来操作 SQLite 数据库hive
插件来进行轻量级本地存储
Flutter 中如何处理导航和路由?
- Flutter 提供了 Navigator 类来管理路由。你可以使用 Navigator.push() 来推送新页面,Navigator.pop() 来弹出当前页面。
- 通过 Named Routes 或 Navigator 2.0 来实现复杂的路由管理。