一、整体架构总览
┌─────────────────────────────────────────────────────────┐
│ iOS 进程 (Process) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Runner (iOS Host App) │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ FlutterEngine 实例 │ │ │
│ │ │ ┌───────────────────────────────────────┐ │ │ │
│ │ │ │ Dart VM │ │ │ │
│ │ │ │ ┌─────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Dart Isolate (main) │ │ │ │ │
│ │ │ │ │ (你写的 Dart 业务代码) │ │ │ │ │
│ │ │ │ └─────────────────────────────────┘ │ │ │ │
│ │ │ │ ┌─────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Dart Isolate (spawned) │ │ │ │ │
│ │ │ │ │ (compute / Isolate.spawn) │ │ │ │ │
│ │ │ │ └─────────────────────────────────┘ │ │ │ │
│ │ │ └───────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ │ │
│ │ │ │ UI Thread│ │IO Thread │ │ GPU Thread │ │ │ │
│ │ │ │(Platform)│ │ │ │ (Raster) │ │ │ │
│ │ │ └──────────┘ └──────────┘ └────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ Native iOS 代码 (AppDelegate, ViewController)│ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ iOS Main Thread ─── GCD Queues ─── 其他系统线程 │
└─────────────────────────────────────────────────────────┘
二、逐层深度解析
2.1 iOS 进程 (Process)
iOS 进程是最顶层的容器,是操作系统分配资源的基本单位。
- 每个 iOS App 运行在独立的沙盒进程中,由
launchd守护进程启动 - 进程拥有独立的虚拟内存空间(通常 4GB 虚拟地址空间)
- 进程内包含:代码段、数据段、堆、栈、内存映射区域
- 一个进程内可以有多个线程
关键点: 无论你的 Flutter App 多复杂,在 iOS 上它始终运行在一个进程内。Runner、FlutterEngine、Dart VM 都是这个进程内的组成部分。
iOS 进程
├── 进程内存空间
│ ├── Runner 的 Native 代码 (Objective-C/Swift)
│ ├── Flutter Engine 的 C++ 代码
│ ├── Dart VM 的运行时
│ ├── Dart 堆内存 (Dart Heap)
│ └── 共享库 (dylib)
├── 文件描述符表
├── 信号处理表
└── 线程表 (所有线程)
2.2 iOS 线程 (Thread)
线程是CPU 调度的基本单位,同一进程内的线程共享内存空间。
iOS 中的关键线程类型
| 线程 | 说明 |
|---|---|
| Main Thread | UI 线程,所有 UIKit 操作必须在此执行 |
| GCD Worker Threads | libdispatch 管理的线程池 |
| pthread | POSIX 线程,底层线程创建方式 |
Flutter 创建的线程
Flutter Engine 启动后会在 iOS 进程内创建4 个核心线程(Task Runner):
┌──────────────────────────────────────────────────────┐
│ Flutter 四大线程 │
├──────────────┬───────────────────────────────────────┤
│ Platform │ 复用 iOS Main Thread │
│ Thread │ 处理 Platform Channel、插件调用、原生交互 │
├──────────────┼───────────────────────────────────────┤
│ UI Thread │ 独立 pthread │
│ (Dart Thread)│ 运行 Dart 代码、构建 Widget Tree/Layer Tree│
├──────────────┼───────────────────────────────────────┤
│ Raster │ 独立 pthread │
│ Thread │ GPU 光栅化,将 Layer Tree 转为 GPU 指令 │
├──────────────┼───────────────────────────────────────┤
│ IO Thread │ 独立 pthread │
│ │ 图片解码、资源加载等耗时 IO 操作 │
└──────────────┴───────────────────────────────────────┘
重要区分: Flutter 的 "UI Thread" 不是 iOS 的 Main Thread。Flutter 的 Platform Thread 才是 iOS 的 Main Thread。
2.3 Runner (iOS Host App)
Runner 是 Flutter 工程中 ios/Runner 目录下的 iOS 宿主工程,本质上就是一个标准的 iOS App。
Runner 的职责
Runner (Xcode Project)
├── AppDelegate.swift / .m
│ └── 创建 FlutterEngine / FlutterViewController
├── Info.plist
│ └── App 配置、权限声明
├── Assets.xcassets
│ └── App Icon、LaunchImage
├── Main.storyboard (可选)
│ └── LaunchScreen
└── Frameworks/
├── Flutter.framework ← Flutter Engine 二进制
└── App.framework ← 编译后的 Dart 代码 (AOT)
Runner 的生命周期
iOS 系统启动进程
│
▼
main() 函数执行
│
▼
UIApplicationMain()
│
▼
AppDelegate 初始化
│
├── 创建 FlutterEngine 实例
│ │
│ ├── 初始化 Dart VM
│ ├── 创建 4 个 Task Runner (线程)
│ └── 加载 Dart AOT snapshot
│
├── 创建 FlutterViewController
│ │
│ ├── 关联 FlutterEngine
│ ├── 创建 Metal/OpenGL 渲染表面
│ └── 注册 Platform Channels
│
└── App 进入 RunLoop
Runner 与 FlutterEngine 的关系
// 典型的 AppDelegate 代码
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
// FlutterAppDelegate 内部持有 FlutterEngine
// 它本质上是一个 UIApplicationDelegate 的实现
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// 此时 FlutterEngine 已经被创建并启动
// Dart VM 已经初始化
// main.dart 的 main() 已经开始执行
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
核心理解:Runner 是"壳",FlutterEngine 是"核心"。 Runner 负责 iOS 层面的事务(权限、推送、深链接等),FlutterEngine 负责 Flutter 的一切。
2.4 Flutter Engine
Flutter Engine 是用 C/C++ 编写的核心运行时,是连接 Dart 代码和底层操作系统的桥梁。
Engine 的组成
FlutterEngine
├── Dart Runtime (Dart VM)
│ ├── Dart Isolate 管理
│ ├── GC (垃圾回收器)
│ └── JIT / AOT 编译器
│
├── Shell (壳层)
│ ├── Platform Shell (iOS 适配层)
│ │ ├── Metal 渲染后端
│ │ ├── 触摸事件转发
│ │ └── 系统 API 桥接
│ └── Task Runner 管理
│ ├── PlatformTaskRunner → iOS Main Thread
│ ├── UITaskRunner → Dart 执行线程
│ ├── RasterTaskRunner → GPU 光栅化线程
│ └── IOTaskRunner → IO 线程
│
├── Skia / Impeller (图形引擎)
│ ├── 2D 渲染 API
│ ├── 文字排版 (txt 库 / libtxt)
│ └── 图片解码
│
├── Text Layout (文字排版引擎)
│
└── Platform Channel 机制
├── MethodChannel
├── BasicMessageChannel
└── EventChannel
Engine 在 iOS 中的存在形式
Flutter.framework (约 40~50 MB, Release 模式)
├── Flutter (Mach-O 动态库)
│ ├── Dart VM 运行时
│ ├── Skia / Impeller 图形库
│ ├── Shell 层 (iOS 适配)
│ └── ICU 国际化数据
└── Headers/
├── FlutterEngine.h
├── FlutterViewController.h
├── FlutterPlugin.h
└── FlutterChannels.h
App.framework (Dart 业务代码编译产物)
├── App (Mach-O 动态库)
│ ├── Dart AOT Snapshot (机器码)
│ └── 资源数据
└── flutter_assets/
├── kernel_blob.bin (Debug 模式)
├── vm_snapshot_data
├── isolate_snapshot_data
└── AssetManifest.json
2.5 Dart VM
Dart VM 是 FlutterEngine 内部的虚拟机运行时,负责执行 Dart 代码。
Dart VM 的两种运行模式
┌─────────────────────────────────────────┐
│ Debug 模式 (JIT) │
│ │
│ Dart 源码 → Kernel Binary → JIT 编译 │
│ → 解释执行 + 热编译为机器码 │
│ │
│ 特点:支持 Hot Reload / Hot Restart │
│ 有 Dart VM 完整编译器 │
│ 性能较低 │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Release 模式 (AOT) │
│ │
│ Dart 源码 → AST → IR → ARM64 机器码 │
│ → 直接 CPU 执行 │
│ │
│ 特点:不支持 Hot Reload │
│ 无 JIT 编译器 (体积更小) │
│ 性能接近原生 │
└─────────────────────────────────────────┘
Dart VM 的内存结构
Dart VM 内存布局
├── New Space (新生代)
│ ├── Semi-Space A (活跃区)
│ └── Semi-Space B (备用区)
│ └── Scavenger GC (复制算法, STW 很短)
│
├── Old Space (老生代)
│ ├── 大对象区
│ └── 普通对象区
│ └── Mark-Sweep / Mark-Compact GC
│
├── Code Space (代码区)
│ └── AOT 编译后的机器码
│
├── Image Space (镜像区)
│ ├── vm_snapshot_data
│ └── isolate_snapshot_data
│
└── Isolate 独有内存
├── 每个 Isolate 有独立的堆
└── Isolate 间不共享内存 (通过消息传递通信)
Dart Isolate 与 iOS 线程的关系
┌─────────────────────────────────────────────────┐
│ │
│ Dart Isolate ≠ iOS Thread │
│ 但 Dart Isolate 运行在 iOS Thread 之上 │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Root Isolate │ ──→ │ UI Thread │ │
│ │ (main) │ │ (固定绑定) │ │
│ └─────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Spawned │ ──→ │ Dart VM 线程池中 │ │
│ │ Isolate │ │ 的某个 pthread │ │
│ └─────────────┘ └─────────────────┘ │
│ │
│ 一个 Isolate 在同一时刻只在一个线程上运行 │
│ 但 Dart VM 可以将 Isolate 调度到不同线程上 │
│ │
└─────────────────────────────────────────────────┘
关键区别:
- Isolate 是 Dart 的并发模型,拥有独立的堆内存,通过 SendPort/ReceivePort 通信
- Thread 是 OS 级别的执行单元,共享进程内存
- Root Isolate 始终运行在 Flutter 的 UI Thread 上
Isolate.spawn()创建的 Isolate 运行在 Dart VM 管理的线程池中
三、协作流程深度解析
3.1 一帧的渲染流程
时间线 ──────────────────────────────────────────────────────→
VSync 信号到达 (16.67ms 一次 @60fps)
│
│ ① Platform Thread (iOS Main Thread)
│ ┌──────────────────────────────┐
│ │ 接收 VSync 回调 │
│ │ 通过 CADisplayLink │
│ │ 通知 UI Thread 开始新一帧 │
│ └──────────────┬───────────────┘
│ │
│ ② UI Thread (Dart Thread)
│ ┌──────────────▼───────────────┐
│ │ 执行 Dart 代码 │
│ │ ├── Build Phase (Widget) │
│ │ ├── Layout Phase (大小/位置) │
│ │ ├── Paint Phase (绘制指令) │
│ │ └── 生成 Layer Tree │
│ └──────────────┬───────────────┘
│ │
│ ③ Raster Thread (GPU Thread)
│ ┌──────────────▼───────────────┐
│ │ 接收 Layer Tree │
│ │ ├── Skia/Impeller 光栅化 │
│ │ ├── 生成 GPU 指令 │
│ │ └── 提交到 Metal/OpenGL │
│ └──────────────┬───────────────┘
│ │
│ ④ iOS 合成器 (Core Animation)
│ ┌──────────────▼───────────────┐
│ │ 合成 Flutter 层与原生 UI 层 │
│ │ 提交到屏幕显示 │
│ └──────────────────────────────┘
3.2 Platform Channel 调用流程
Dart 代码 (UI Thread) Native 代码 (Platform Thread)
│ │
│ MethodChannel.invokeMethod('getBattery') │
│ ─────────────────────────────────────→ │
│ [序列化为二进制消息] │
│ [从 UI Thread 调度到 Platform Thread] │
│ │
│ ┌──────────────▼──────┐
│ │ iOS Main Thread │
│ │ 执行原生代码 │
│ │ UIDevice.current │
│ │ .batteryLevel │
│ └──────────────┬──────┘
│ │
│ ←───────────────────────────────────── │
│ [结果序列化] │
│ [从 Platform Thread 调度回 UI Thread] │
│ │
▼ ▼
收到 Future 结果 调用完成
3.3 多 Engine 场景 (Add-to-App)
iOS 进程
├── Runner
│ ├── FlutterEngine A (主引擎)
│ │ ├── Dart VM (进程内唯一,共享) ◄──── 重要!
│ │ ├── Root Isolate A
│ │ ├── 4 个线程 (Platform/UI/Raster/IO)
│ │ └── FlutterViewController A
│ │
│ ├── FlutterEngine B (第二个引擎)
│ │ ├── Dart VM (复用同一个) ◄──── 同一个 Dart VM
│ │ ├── Root Isolate B (独立的 Isolate)
│ │ ├── 4 个线程 (Platform共享/UI独立/Raster独立/IO独立)
│ │ └── FlutterViewController B
│ │
│ └── FlutterEngineGroup (管理多引擎)
│ └── 共享 Dart VM,减少约 99% 的额外内存开销
核心要点: 一个 iOS 进程中只有一个 Dart VM 实例,但可以有多个 FlutterEngine,每个 Engine 有自己独立的 Root Isolate。
四、关系总结图
┌─────────────────────────────────────────────────────┐
│ │
│ 包含关系 (从外到内): │
│ │
│ iOS 进程 │
│ └── Runner (iOS Host App) │
│ └── FlutterEngine │
│ ├── Dart VM (进程唯一) │
│ │ └── Dart Isolate (可多个) │
│ ├── Skia / Impeller │
│ └── Shell (平台适配层) │
│ │
│ 运行关系 (线程维度): │
│ │
│ iOS Main Thread ═══ Flutter Platform Thread │
│ │ │ │
│ │ ├── 插件调用 │
│ │ ├── 原生 UI 交互 │
│ │ └── 生命周期管理 │
│ │ │
│ Flutter UI Thread ─── Dart Root Isolate 运行于此 │
│ │ │ │
│ │ ├── Widget 构建 │
│ │ ├── 布局计算 │
│ │ └── 绘制指令生成 │
│ │ │
│ Flutter Raster Thread ─── GPU 光栅化于此 │
│ │ │
│ Flutter IO Thread ─── 资源加载/图片解码于此 │
│ │ │
│ Dart VM 线程池 ─── spawned Isolate 运行于此 │
│ │
└─────────────────────────────────────────────────────┘
五、常见误区澄清
误区 1:Flutter 的 UI Thread 就是 iOS 的 Main Thread
错!
- Flutter Platform Thread = iOS Main Thread
- Flutter UI Thread 是单独的 pthread,专门运行 Dart 代码
- 在 Dart 代码里调用
Platform Channel时,消息从 UI Thread 发送到 Platform Thread(即 iOS Main Thread)
误区 2:Dart Isolate 就是一个线程
错!
- Isolate 是 Dart 的并发抽象,拥有独立的堆内存
- Isolate 运行在线程之上,但两者不是一一对应关系
- Dart VM 内部使用线程池来调度 Isolate
- Root Isolate 固定绑定在 UI Thread 上,但 spawned Isolate 可能被调度到不同的线程
误区 3:多个 FlutterEngine 就有多个 Dart VM
错!
- 一个 iOS 进程中只有一个 Dart VM
- 多个 FlutterEngine 共享同一个 Dart VM
- 每个 FlutterEngine 有自己独立的 Root Isolate
- 使用
FlutterEngineGroup可以高效创建多引擎,内存开销极小
误区 4:Runner 就是 Flutter
错!
- Runner 只是一个标准的 iOS App 工程(壳)
- 真正的 Flutter 运行时是
Flutter.framework中的 FlutterEngine - Runner 可以同时包含原生 Swift/ObjC 代码和 Flutter 页面
- 在 Add-to-App 场景中,Runner 甚至不叫 Runner,就是你已有的 iOS 工程
六、实际影响与性能调优启示
| 场景 | 涉及组件 | 优化方向 |
|---|---|---|
| 界面卡顿 | UI Thread (Dart) | 减少 build() 复杂度,使用 const Widget |
| 光栅化卡顿 | Raster Thread | 减少 saveLayer、clipPath 等 GPU 密集操作 |
| 平台通信慢 | Platform Thread ↔ UI Thread | 减少 Channel 调用频率,批量传输数据 |
| 图片加载慢 | IO Thread | 预缓存、降低分辨率、使用 precacheImage |
| 内存爆炸 | Dart VM (Isolate Heap) | 控制 Isolate 数量、及时释放大对象 |
| 原生插件阻塞 | Platform Thread (Main Thread) | 插件内部开子线程处理耗时逻辑 |
| App 启动慢 | Engine 初始化 + Dart VM 启动 | 预热 Engine (FlutterEngine 提前初始化) |