Flutter
Flutter 的独特之处是自己渲染一切:不借道系统控件,而是用引擎把 Widget 画到屏幕上,因此跨端像素级一致。主线条:Dart 语言 → Widget 与三棵树 → 状态管理 → 平台通道 → 发布与性能。示例基于 Flutter 3.x 稳定线编写,需在安装 Flutter SDK 的环境验证。
Flutter 是什么:三层架构
| 层 | 内容 | 类比 |
|---|---|---|
| Framework(Dart) | Widget、布局、动画、手势、Material/Cupertino | 你写代码的地方 |
| Engine(C++) | 渲染(Impeller/Skia)、文本、平台通道、Dart VM | 系统之上的一层「画布」 |
| Embedder | 与 iOS/Android/桌面原生宿主桥接 | 每个平台各一套薄壳 |
关键推论:渲染不依赖系统控件,所以两端 UI 一致、动画可控;代价是引擎体积与首帧成本、部分系统级能力要走通道。
Dart 语言速览(够用就好)
- 一切皆对象,类型可空(
String?),final/const优先; - 集合:
List/Set/Map;集合字面量简洁; - 异步:
Future/async/await+Stream(流,适合事件序列); - 类:构造器语法、
factory、named参数、不可变推荐const构造; - Flutter 运行时无反射常规用(tree-shaking),JSON 解析手写或 codegen(json_serializable/freezed)。
dart
Future<void> fetchUsers() async {
final resp = await http.get(Uri.parse('https://api.example.com/users'));
final list = jsonDecode(resp.body) as List;
// list.map(...) 转模型
}Widget 与「三棵树」
Widget 只是配置描述(不可变),真正干活的是它背后的树:
- Widget 树:你写的声明(每次 rebuild 都新建);
- Element 树:Widget 与 RenderObject 的粘合,负责 diff(框架帮你维护);
- RenderObject 树:真正布局/绘制。
所以放心写 build——Flutter 只对有变化的部分重建 Element,而不是每次整体重绘。
状态组件两种写法
dart
// 无状态
class Greeting extends StatelessWidget {
const Greeting({super.key, required this.name});
final String name;
@override
Widget build(BuildContext context) => Text('你好,$name');
}
// 有状态
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _count = 0;
@override
Widget build(BuildContext context) {
return FilledButton(
onPressed: () => setState(() => _count++),
child: Text('次数 $_count'),
);
}
}注意:Widget 重建(父级 rebuild)不等于 State 丢失——State 附着在 Element 上,用 key 控制是否复用/重建 State。
布局速查
| 场景 | 组件 |
|---|---|
| 纵向/横向排布 | Column / Row(主轴对齐、Expanded 占位) |
| 叠放 | Stack |
| 容器装饰 | Container、DecoratedBox |
| 滚动列表(懒加载) | ListView.builder / GridView.builder |
| 自适应尺寸 | Flexible、AspectRatio、LayoutBuilder |
| 安全区 | SafeArea、MediaQuery |
| 对齐与间距 | Padding、Align、Spacer、SizedBox |
核心习惯:小屏高复用组件都写成 const 构造(const Text(...)),让重建跳过。
状态管理谱系(从简到繁)
| 方案 | 适合 | 备注 |
|---|---|---|
| setState | 单个组件内 | 最基础,别到处搬 |
| ValueNotifier + ValueListenableBuilder | 单个全局小状态 | 轻量 |
| InheritedWidget / Provider | 少量跨层共享 | 官方推荐的入门层级 |
| Riverpod | 中大型、追求类型安全与可测试 | 当前社区主流推荐之一 |
| Bloc | 重逻辑、事件驱动团队 | 样板多,规则明确 |
选型建议:小项目 Provider 起步;项目明显增长或多人协作再迁移 Riverpod/Bloc,不要一上来上最重的。页面级请求状态 + 全局会话/主题是两种状态,分层管理(见本站分层纪律)。
导航路由
Navigator.push(MaterialPageRoute(...))命令式跳转;- 命名路由/
go_router(声明式深链、守卫),App 复杂后用go_router; - 传参用构造参数或路由参数对象;回传结果用
Navigator.pop(context, result)。
与原生交互:平台通道
MethodChannel:Dart 调原生方法(平台侧写同名字符串方法);- 更现代的
Pigeon:生成类型安全通道代码,减少字符串拼写错误; dart:ffi:需要极高性能时直接绑 C 库;- 推荐顺序:优先找维护良好的官方/知名插件(如
shared_preferences、path_provider、image_picker),确实没有再自己写通道。
平台侧别忘了:iOS 的 Info.plist 权限文案、Android 的 Manifest 权限与 ProGuard 配置常是「插件装上却不工作」的元凶。
依赖与工程
pubspec.yaml管理依赖;flutter pub add xx添加;flutter analyze(静态检查)+dart format进 CI;- 测试:
test单测、widget_testWidget 测试、integration_test真机/模拟器端到端; - 环境区分:
--dart-define=API_BASE_URL=...注入环境变量,String.fromEnvironment读取。
发布
bash
flutter build apk --release # Android APK
flutter build appbundle --release # Android AAB(上 Play 用)
flutter build ios --release # iOS(需 macOS + 签名)
flutter build windows / macos / linux # 桌面(各自系统)iOS 仍要走证书/TestFlight 流程、Android 仍要签名,见打包、签名与发布;桌面端参考桌面应用:Electron / Tauri。
性能与调试(详见性能与稳定性)
- 帧预算:Flutter 目标是 60/120fps,动画掉帧先开 DevTools 的 performance 看耗时区间(build/layout/paint);
const构造 +RepaintBoundary减少重绘范围;- 图片:
cached_network_image/平台缓存,列表图用缩略图尺寸; - 列表:
ListView.builder懒加载,不要ListView(children:)塞上千项; - 热重载(r)改代码、热重启(R)改 main/全局状态,调试两件套。
常见坑速查
| 坑 | 现象 | 对策 |
|---|---|---|
| 忘加 const | 大量 rebuild 性能浪费、lint 警告 | 小叶子组件尽量 const |
| 布局溢出 | RenderFlex overflowed 黄黑条 | Row/Column 里给可伸缩项加 Expanded/Flexible |
| 列表用错 | 一次性建上千 View 卡死 | 一律 builder 系列懒加载 |
| 原生插件缺配置 | Android/iOS 平台报错或空白 | 先查 Info.plist / Manifest 权限与混淆 |
| 状态管理搬全家 | 组件间乱传回调难维护 | 状态就近 + 按层治理 |
| JSON 手写解析崩 | 字段类型不符运行时炸 | freezed/json_serializable + 单元测试 |
| 文本缩放溢出 | 系统大字体下 UI 溢出 | 测试大字体,用 Flexible/ellipsis |
| 跨端像素差异 | 部分平台字体/滚动条观感不同 | 每端真机回归 UI 清单 |
| 版本升级裸奔 | 升级 Flutter 后插件不兼容 | 用官方 upgrade 指南按小版本渐进 |
| 发布包不含环境区分 | 打到生产误用测试环境 | dart-define 注入 + 构建产物校验 |
| 忘记处理空值/空列表 | 无数据时白屏或崩 | 统一 empty/error/loading 三态组件 |
检查清单
- [ ] 布局组件用对了(列表用 builder,溢出用 Flexible);
- [ ] 状态分层明确:页面级 + 全局级分开治理;
- [ ] 原生能力优先找官方插件,自写通道用 Pigeon 类型安全方案;
- [ ] 平台侧权限/文案/混淆已配置;
- [ ] flutter analyze 与测试在 CI 通过;
- [ ] release 构建可出包,环境变量隔离正确;
- [ ] 真机过一遍大字体、横竖屏、弱网三回归。
相关链接:技术全景与选型 · React Native · 性能与稳定性 · 打包、签名与发布 · 写作规范见客户端开发索引。