初见 Dart:这门新语言如何让你的 App「动」起来?

221 阅读9分钟

大家好,我是Petter Guo

一位热爱探索全栈工程师。在这里,我将分享个人Technical essentials,带你玩转前端后端DevOps 的硬核技术,解锁AI,助你打通技术任督二脉,成为真正的全能玩家!!

如果对你有帮助, 请点赞+ 收藏 +关注鼓励下, 学习公众号为 全栈派森

时间过的好快, 本人接触业务比较复杂, 最近一直在搞跨平台相关的技术, 比如很火的两大框架 Flutter & ReactNative, 本期你将有如下收获:

  1. 🍰 Flutter底层架构
  2. 🍦 Flutter核心组件
  3. ⛽️ Dart常用语法
  4. 🙋 Flutter vs RN

Flutter底层架构

  1. 顶层:框架层 (The Framework)

    这一层完全由 Dart 语言 编写,是我们作为开发者直接打交道的部分。

  • Dart Platform: 包含 Dart 语言、核心库和 Dart VM(虚拟机)。
  • Widgets (组件): Flutter 的核心概念。所有的 UI 都是由 Widget 组成的,它描述了 UI 的一部分应该如何渲染和交互。
  • 基础 Widgets:Text, Image, Row, Column 等。
  • 渲染 Widgets:
    • Material Design: 实现 Google 的 Material 设计规范(如 Scaffold, AppBar)。
    • Cupertino: 实现 Apple 的 iOS 设计规范。
  • Rendering (渲染): 提供了抽象的渲染模型,包括 RenderObject、布局、绘制等。
  • Animation, Gestures & Painting: 处理动画、手势识别和底层绘图逻辑。

核心思想: Flutter 框架只提供 抽象的 UI 组件一套渲染规范

  1. 中间层:引擎层 (The Engine)

    这一层主要由 C++ 编写,它负责执行 Dart 运行时环境,并将上层的 Dart 代码渲染到萤幕上。

  • Skia 引擎 (Skia Graphics Engine): 这是 Flutter 最关键的部分。 Skia 是一个高性能的 2D 渲染引擎,也是 Chrome 和 Android 采用的图形库。 Flutter 依靠 Skia 在移动设备上绘制每一个像素
  • 优势: 这使得 Flutter 完全绕过了 原生 OEM(原始设备制造商)的 UI 组件。应用程式只需一个「画布」,所有的按钮、文本、动画都由 Skia 直接绘制。
  • Dart Runtime: Dart 虚拟机(VM)和 AOT/JIT 编译器,负责运行 Dart 代码。
  • Text Layout: 处理文本布局和字体渲染。
  • Platform Channels (平台通道): 实现 Dart 代码与原生平台(如 iOS 的 Swift/Objective-C 或 Android 的 Java/Kotlin)之间的通信。这是 Flutter 访问原生 API(如 GPS、蓝牙)的唯一途径。

核心思想: 引擎层是 底层执行者,负责将 Dart 的指令翻译成像素并绘制出来。

  1. 底层:嵌入层 (The Embedder)

    这是与 特定操作系统(OS) 交互的层级。

  • 平台特定的程式码: 这部分是 Dart 运行时和底层 OS 之间粘合剂。
  • Android: 使用 Java/Kotlin,将 Flutter 引擎作为 Activity 嵌入。
  • iOS: 使用 Swift/Objective-C,将 Flutter 引擎作为 ViewController 嵌入。
  • 访问原生 API: 嵌入层提供了底层的系统服务、生命周期事件、输入事件(触摸、滑鼠)等。

核心思想: 嵌入层是 宿主,负责提供一个原生环境来运行和承载 Flutter 引擎。

Flutter优势

这种分层架构带来了以下独特的优势:

  1. 高性能 (High Performance): 由于 Dart 代码可以 AOT (Ahead-of-Time) 编译成高效的 ARM 机器码,再加上直接使用 Skia 引擎渲染,性能可以媲美原生应用
  2. UI 一致性 (UI Consistency): 由于不依赖原生系统的 UI,Flutter 应用在​​任何版本或型号的设备上都能保持像素级的一致性
  3. 消除 Bridge 瓶颈 (No Bridge): Flutter 不使用 React Native 那样的 JSON 异步 Bridge,所有的 UI 逻辑都在 Dart VM 中运行,避免了序列化和跨线程通信的开销。

Flutter核心组件

1. 📂 布局与结构 Widgets (Layout & Structure)

Widget作用关键属性示例场景
Scaffold脚手架。提供应用程式的基本结构,如抽屉、底部导航栏、浮动按钮等。appBar, body, drawer, bottomNavigationBar每个页面/屏幕的顶层 Widget。
Container容器。最基础的布局/装饰 Widget,用于添加边距、填充、颜色、装饰等。child, padding, margin, color, decoration给子 Widget 设置背景色和边距。
Row / Column行/列。在水平 (Row) 或垂直 (Column) 方向上排列多个子 Widget。children (Widget 列表), mainAxisAlignment, crossAxisAlignment实现线性布局。
Center居中。将其子 Widget 居中放置。child将单个元素放在萤幕中央。
Padding填充。在其子 Widget 周围添加内部间距(填充)。padding (通常使用 EdgeInsets.all 等)调整 Widget 内部空间。
SizedBox尺寸。用于控制子 Widget 的大小或简单地创建空白间距。width, height, child创建两个 Widget 之间的固定间隔。

2. 🧱 基础内容与交互 Widgets (Content & Interaction)

Widget作用关键属性示例场景
Text文本。用于显示静态文本。data (文本内容), style (TextStyle), textAlign显示标题、描述、正文。
Image图片。用于显示图片,支持本地资源、文件或网路图片。image (Asset/NetworkImage), fit, width, height显示应用 Logo、用户头像、网路图片。
Icon图标。用于显示 Material 或 Cupertino 图标。icon (Icons.xxx), color, size菜单图标、操作按钮图标。
ElevatedButton按钮。带有阴影效果的凸起按钮。onPressed (点击回调), child提交表单、执行操作。
TextField文本输入框。用于接收用户输入。controller, decoration (InputDecoration), onChanged, keyboardType用户名/密码输入、搜寻框。
ListView列表。用于垂直滚动的长列表,只渲染可见部分(性能优化)。childrenitemBuilder (Factory 模式)显示新闻列表、聊天记录。

3. 🔄 状态管理与动态 Widgets (State Management)

Widget作用区别示例场景
StatelessWidget无状态 Widget。一旦创建,它的属性(数据)就不会改变。数据是固定的 (final),没有内部状态。显示静态文本、Logo、静态图标。
StatefulWidget有状态 Widget。其内部数据可以在 Widget 生命周期内发生变化。包含一个 State 对象,通过调用 setState() 来触发 UI 重新绘制。带有计数器的按钮、复选框、动态列表。

✍️ Dart 常用语法特性

Flutter 使用 Dart 语言,它是一种面向对象、类基的语言,同时支持 AOT(编译成机器码)和 JIT(即时编译,用于热重载)。

1. 类型与变量

  • 类型推断: 大多数时候可以使用 var,Dart 会自动推断类型。
var name = 'Alice'; // String
var year = 1977;   // int
  • 明确类型: 也可以明确声明。
String name = 'Bob';
int age = 30;
  • 不变性 (Immutability):
  • final: 运行时常量,只能赋值一次。
  • const: 编译时常量,在编译时就确定值。
final String uid = getUserId(); // 运行时确定
const PI = 3.14159;             // 编译时确定
  • 可空类型 (Null Safety): 这是 Dart 2.12+ 的重要特性。
  • String?: 变量可以是 String 类型,也可以是 null
  • String: 变量不能null
  • ! (断言): 告诉编译器「我相信它不是 null」。

2. 函数与箭头语法

  • 普通函数:
int add(int a, int b) {
  return a + b;
}
  • 箭头函数: 适用于只有单个表达式的函数。
int multiply(int a, int b) => a * b;

3. 构造函数 (Constructors)

Dart 提供了强大的构造函数语法,常在 Flutter Widget 中使用:

  • 简化赋值: 直接在构造函数中为实例变量赋值。
class Person {
  final String name;
  Person(this.name); // 简洁地将参数赋值给 name
}
  • 命名构造函数: 创建多个、有特定用途的构造函数。
Person.fromJson(Map data) {
// ...
}
  • 工厂构造函数 (Factory): 用于复杂的对象创建逻辑(如单例模式或返回子类型)。

4. 异步编程 (Asynchrony)

Dart 使用 Futureasync/await 处理异步操作(如网路请求)。

// 声明函数是异步的
Future<String> fetchData() async {
  // 使用 await 等待结果,代码看起来像同步一样
  var response = await httpClient.get('...');
  return response.body;
}

Flutter vs RN

1. ⚛️ React Native (JS + Bridge + 原生元件)

  • 技术栈: JavaScript / TypeScript + React。
  • 工作原理: React Native 依赖于一个 Bridge(桥接器),将 JavaScript 逻辑转换为原生操作。它使用 原生 UI 元件(如 Android 的 TextView,iOS 的 UILabel)进行渲染。
  • 优势: 能够提供完全的原生体验,因为它使用的就是平台自带的 UI 元素。可以充分利用现有的原生代码和生态。
  • 瓶颈: Bridge 的 JSON 序列化与异步传输 带来性能开销,尤其在高频度交互或动画时,容易造成卡顿。

2. 🐦 Flutter (Dart + Skia 引擎 + 自绘元件)

  • 技术栈: Dart 语言。
  • 工作原理: Flutter 跳过了原生 UI 元件和 Bridge。它自带一个高效的 Skia 图形渲染引擎。应用程式启动时,Flutter 创建一个 Canvas(画布),然后在上面用 Dart 代码直接绘制 自定义的 Widget
  • 优势: 接近原生的性能,因为它被编译成 ARM 机器码。 UI 表现力强,因为它不依赖原生系统的 UI,实现了 像素级的控制
  • 瓶颈: 文件体积较大,且没有使用平台原生的 UI 元素,在某些极度依赖原生系统风格的应用上可能显得突兀。

二、选择决策矩阵:五个关键维度

决策维度Flutter (Dart)React Native (JS/TS)选择建议
1. 团队现有技能需要学习 Dart 语言 和 Flutter 框架的思维模式。技能门槛低,可以重用 React/Web 前端 团队的大部分经验。前端背景强:选 RN;无历史包袱或有原生背景:选 Flutter。
2. 性能与 UI 复杂度性能优异,因其编译为原生机器码,且自绘引擎消除了 Bridge 瓶颈。性能良好,但在复杂动画和高频交互上可能因 Bridge 而略输 Flutter。对性能要求极高、复杂动画:选 Flutter;标准业务应用:RN 足够。
3. 生态系统与第三方库较新,社群成长快,但第三方库的数量和成熟度不如 RN。极其庞大和成熟,大量库可供选择。与原生生态桥接成熟。依赖大量现有轮子:选 RN;愿意自建或 Bridge 原生代码:选 Flutter。
4. 开发效率与热重载优秀的 Hot Reload,但在 Native Code 变更时需重新编译。拥有 Fast Refresh,JS 代码更新极快。原生代码变更也需重新编译。基本持平;RN 在 JS 迭代上更胜一筹。
5. 多平台支持广泛: iOS, Android, Web, Desktop (Windows, macOS, Linux)。主流: iOS, Android;Web 需额外使用 React Native for Web。未来可能扩展到桌面端:选 Flutter;专注于移动端:RN 足够。

滑到这里定然有所收获 ⛽️⛽️