Skip to content

00 · 学习路线图 ​

这是全系列的第一篇,也是唯一一篇必读的索引。 它回答三个问题:按什么顺序学、每周该到什么程度、哪些坑文档已经替你踩过了。


一、30 秒速览:这个项目是什么 ​

HaierEnergy 是一个生产级 Flutter App(包名 com.haier.energy.platform,Dart 包名 haierenergy),由 uni-app 老项目迁移而来。

维度规模
Dart 文件lib/ 1118 个(含 273 个生成文件;ui/ 434、data/ 353、domain/ 108、he_components/ 108)
业务模块设备管理、电站、家庭、参数下发、高级功能、用户中心
技术栈Riverpod 2.6 + GoRouter 14 + Freezed 2.5 + Retrofit 4 + Dio 5
测试test/ 目录镜像 lib/,共 251 个测试文件(ui/ 下 135 个)
团队规模痕迹有编码规范、守护脚本、Figma token 漂移检测、Apifox 契约校验

这意味着什么:你不是在看一个 Demo,而是在读一个真实的中大型工程。好处是学到的都是能直接用的;坏处是没人会手把手教你 Dart 语法——所以本系列第 01、02 章就是补这个的。


二、按周学习路径 ​

假设你每天能投入 2~3 小时。如果你的时间不连续,按「阶段」而非「周」推进即可。

第 1 周:能读懂代码 ​

天内容产出
101-Dart语言基础 前半(类型、空安全、final/const)能看懂任意一个 lib/ 下文件的变量声明
201 后半(异步、集合、级联、sealed)能读懂 lib/domain/models/result.dart
302-Flutter核心基础 前半(Widget 树、Stateless/Stateful)能说出 ConsumerWidget 与 StatelessWidget 的区别
402 后半(约束布局、常见溢出、BuildContext)遇到 RenderFlex overflowed 知道往哪查
5通读 lib/ui/home/views/agent_home_page.dart(先不求甚解)能指出哪几行是「取状态」、哪几行是「发请求」

周末自检:不查文档,能解释 Result<T> 是什么、AsyncValue 有哪三态。

第 2 周:补通用内功(项目里没写,但你不能不会) ​

项目用 Riverpod + GoRouter 这类重框架,导致下面这些通用知识在代码里几乎找不到踪影——但不学,你第三个页面就会卡住:

天内容为什么必须学
103-Flutter渲染原理与生命周期项目大量 ConsumerWidget(无状态),你可能写完三个页面都没写过一次 initState
204-Flutter布局与滚动进阶一旦要做「滚动时折叠的详情页头」,ListView 就不够用了
305-Flutter交互与动画Flutter 没有 DOM 事件冒泡,手势靠「竞技场」抢,这是前端最大的思维差异点
406-Dart异步并发与进阶语法Dart 是单线程事件循环,Isolate 是唯一真并发手段
5回头重读 agent_home_page.dart这次应该能看懂 80% 了

为什么「Dart 异步」排在 Flutter 三篇之后,而不是紧跟 Dart 基础? 因为事件循环、Isolate、Stream 需要「Flutter 单线程渲染模型」这个前置认知才好理解。放在 02 之后立刻讲会非常枯燥且没有上下文;放在 03~05 之后,你已经见过渲染管线,再讲事件循环就有落点了。

第 3 周:摸清项目骨架 ​

天内容产出
107-项目架构总览能在目录树里 10 秒内定位到任意功能
208-状态管理Riverpod能自己写一个 @riverpod class
309-数据层链路能新增一个 Repository 方法
411-组件与主题知道 88 个 He 组件里哪个能直接用,不再重复造轮子
512-分页与列表能照 PagedListBody 写一个新的分页列表

周末自检:能独立创建一个带分页列表的新页面(可以先不接接口,用 Mock)。

第 4 周:能独立交付 ​

天内容产出
110-页面开发实战端到端走通「路由 → 模型 → ViewModel → 页面 → 接口」
213-路由与导航能注册新路由、传参、处理返回
314-国际化新增一条文案走通全流程
415-权限与设备能力知道业务权限和系统权限是两套东西
516-工程化与调试 + 17-常见陷阱与速查表能本地出包、能自己排查常见报错

毕业标准:从零新增一个完整业务模块(含列表页、详情页、接口对接、文案、权限),通过 bash scripts/precheck.sh。

第 5 周起:进阶 → 高级 → 资深(能力分级) ​

到这里"能交付"已经达成,后面按能力等级往上走,不再按天排:

阶段目标必读产出
第 5~6 周 · 进阶能独立优化与补全18 本地存储 · 19 测试实战 · 20 异常监控 · 36 状态恢复 · 38 埋点给现有页面补测试、埋点、异常处理与状态恢复
第 7~8 周 · 高级能设计复杂模块28 自定义渲染 · 29 动画工程化 · 40 图表可视化 · 37 后台任务 · 39 IoT 协议独立实现图表看板、后台同步、设备通信链路
第 9 周起 · 资深能做架构与治理决策31 架构分层 · 30 包与插件 · 43 Monorepo · 42 安全纵深 · 34 动态化输出架构评审 / 组件库规划 / 安全与工程化治理方案

分级不是"看完才算",而是对应岗位能力:能交付对应初中级,能设计优化对应高级,能做取舍决策对应资深。面试对照见 IM 面试题。


三、章节依赖关系 ​

mermaid
flowchart LR
    A["00 路线图"] --> B["01 Dart 基础"]
    B --> C["02 Flutter 核心"]
    C --> D["03 渲染原理"]
    C --> E["04 布局滚动"]
    C --> F["05 交互动画"]
    D --> G["06 异步并发"]
    C --> H["07 项目架构"]
    H --> I["08 Riverpod"]
    H --> J["09 数据层"]
    I --> K["10 页面实战"]
    J --> K
    H --> L["11 组件主题"]
    K --> M["12 分页列表"]
    K --> N["13 路由导航"]
    H --> O["14 国际化"]
    H --> P["15 权限设备"]
    L --> Q["16 工程化"]
    M --> R["17 速查表"]
    Q --> R

三条可选捷径:

  • 急着改 bug(第 1 天就要动代码):02 → 07 → 17,先能跑起来再说
  • 只要能写页面(不做架构决策):01 → 02 → 08 → 10 → 11
  • 要接接口:01 → 07 → 09(可跳过 03~06)

四、练习怎么跑 ​

本系列的练习分两种载体,不要搞混:

载体 A:lib/main_playground.dart(章节 03~06) ​

早期版本在项目里放了同名空白练习场,当前 checkout 已删除。需要时临时重建一个最小入口 (只包 MaterialApp,不属于业务代码,练完删除、不要提交),把文档里的 Demo 粘进 PlaygroundPage:

bash
fvm flutter run -t lib/main_playground.dart

⚠️ 注意:lib/main_test.dart 不是练习场。它是「测试环境后端」的 App 启动入口 (appMain(forcedEnvironment: Environment.test)),会拉起整个 App。同理 main_prod.dart 是生产环境入口。这两个都是正式文件,不要拿来做实验。

playground 刻意只包 MaterialApp,不包 ProviderScope / 主题 / i18n delegate——所以:

在 playground 里写结果
纯 Flutter Widget(Row/Column/ListView 等)✅ 正常
ref.watch / ref.read❌ No ProviderScope found
He 组件、AppTokens.of(context)❌ 取不到(null)
RuntimeI18n.ofNonNull(context)❌ assert 失败

这个限制不是缺陷而是设计:03~06 章全是通用知识,本来就不该依赖项目框架。

载体 B:test/ 下的 widget test(章节 07~17) ​

项目已有完整测试目录,镜像 lib/ 结构。改一改就能跑:

bash
fvm flutter test test/ui/core/widgets/paged_list_body_test.dart

重点可参考的现成用例:

  • test/ui/device/view_models/device_list_view_model_test.dart
  • test/data/repositories/device/device_repository_test.dart
  • test/core/i18n/runtime_i18n_engine_test.dart
  • test/ui/core/widgets/paged_list_body_test.dart

五、项目红线(写代码前必须知道) ​

这些来自项目 AGENTS.md 与 docs/coding-standards.md,违反会在 code review 被打回:

#红线正确写法
1所有命令加 fvm 前缀fvm flutter pub get(不是 flutter pub get)
2颜色/间距/字体必须走 tokenAppTokens.spacingMd(不是 SizedBox(height: 16))
3图片资源用强类型引用Assets.images.xxx.image()(不是 Image.asset('...'))
4业务权限走 hasPermissionref.watch(authViewModelProvider).hasPermission('app:b:addPlant')
5日志用 AppLoggerAppLogger.I.d(...)(不是 print())
6生成文件要提交*.g.dart、*.freezed.dart、lib/generated/assets.gen.dart 全进 git
7出包走脚本scripts/build.sh android --release(不直接 fvm flutter build)
8构建前跑预检bash scripts/precheck.sh

六、依赖版本基线(写错了会报莫名其妙的错) ​

照着网上的教程敲代码报错时,先查这张表——版本不对是新手报错的头号原因。

依赖本项目版本提醒
Flutter SDK>=3.5.0 <4.0.0(fvm 3.27.4 / Dart 3.6.2)
flutter_riverpod / riverpod_annotation^2.6.1是 2.x 不是 3.x!语法差异极大
dio^5.7.0
retrofit^4.4.1
go_router^14.6.2
freezed^2.5.7
flutter_screenutil^5.9.3designSize Size(750, 1624)
tdesign_flutter^0.2.7
flutter_easyloading^3.0.5

Riverpod 2.x vs 3.x 的坑:网上大量教程是 3.x 写法。本项目是 2.6.1, 用 3.x 语法(如新的 Notifier 初始化方式、Ref 泛型参数)会直接编译失败。 本系列 08-状态管理Riverpod 严格按 2.6.1 撰写。


七、现有 docs/ 文档地图(含过时标注) ​

项目 docs/ 下已有 15 篇约 6600 行文档。本系列不修改它们,但你迟早会翻到,所以这里给一张地图。

值得读的 ​

文件行数什么时候读
docs/coding-standards.md172入职第一天就读,编码规范
docs/architecture.md375读本系列 07 时对照看
docs/api-integration-flow.md474要接接口时读,与本系列 09 互补
docs/freezed-model-guide.md369写模型时读
docs/theme-guide.md219用主题 token 时读
docs/figma-component-mapping.md122对着设计稿还原 UI 时读
docs/project-overview.md43想知道项目边界时读

⚠️ 已过时,以本系列为准 ​

docs/README.md(1100 行)是一份「前端转 Flutter 入门指南」,但有三处内容已与代码不符:

#文档写的代码实际影响
1package:aiwork/...package:haierenergy/...照抄 import 直接编译失败
2AppLocalizations.of(context)RuntimeI18n.ofNonNull(context)该项目走运行时词条,不走 gen-l10n
3学习路径指向 lib/ui/audit/completion/该目录已不存在(现为 device/ paramSet/ plant_detail/)按图索骥会找不到文件

结论:docs/README.md 的思路和概念对照表仍有价值,但代码路径、包名、API 一律以本系列为准。

内容重复的(不必都读) ​

多语言相关有 4 篇,内容大量重叠:

  • docs/language.md(1127 行)
  • docs/l10n-flow.md(821 行)
  • docs/i18n-analysis.md(528 行)
  • docs/l10n-architecture.md(475 行)

读本系列 14-国际化 即可,它以代码为准重新梳理了唯一正确的链路。

用途不明 / 迁移临时文档 ​

docs/1.md(576 行)、docs/language copy.md(306 行,副本)、docs/device-page-migration-gap-analysis.md(370 行,迁移期缺口分析)、docs/ui_dto_import_audit.md(47 行)、docs/uniapp-migration-workflow.md(13 行)。

根目录另有冗余副本:1.md、AGENTS copy.md、CLAUDE.md。这些属于历史遗留,初学阶段忽略。


八、你已经会前端,所以这些概念可以直接迁移 ​

前端本项目对应详见
React / Vue 组件ConsumerWidget / ConsumerStatefulWidget02
useStateref.watch(provider)08
useEffect(() => fetch(), [])@riverpod class 的 build()08
useEffect 返回的清理函数ref.onDispose()08
dispatch(action)ref.read(xProvider.notifier).method()08
refetchref.invalidateSelf()08
TypeScript interface@freezed class01
Either<Error, T>Result<T>(Ok / ErrorResult)09
Axios 拦截器Dio 拦截器链09
Vue Router / React RouterGoRouter13
CSS 变量 / 主题 tokenAppTokens11
i18n.t('key')RuntimeI18n.ofNonNull(context).t('key')14
React keyFlutter Key(ValueKey / GlobalKey)03
DOM 事件冒泡没有冒泡,手势竞技场 GestureArena05
Web WorkerIsolate06
@media 响应式LayoutBuilder / MediaQuery + ScreenUtil04
CSS keyframesAnimationController + Tween05

九、能力分级索引(初中高资深对照) ​

把全系列按"能力等级"重新组织,方便按目标跳读:

等级覆盖内容对应章节
入门(能读懂、能写简单页面)Dart 基础、Flutter 核心、布局、交互动画、项目骨架01 02 03 04 05 07 08 09
进阶(能独立交付完整功能)页面实战、列表、路由、国际化、权限、存储、测试10 12 13 14 15 16 17 18 19 36
高级(能做复杂模块与性能)自定义渲染、动画、图表、后台任务、异常、埋点、IoT20 22 28 29 37 38 39 40 41
资深(能做架构与治理决策)架构分层、状态选型、包管理、安全、动态化、Spec 工作流11 26 27 30 31 32 33 34 42 43

同一篇文章可能跨等级(如 05 交互动画 入门要会用,高级要做动效工程化),这里按最典型的使用场景归类。


十、常见疑问 ​

Q:我要不要先把 Flutter 官方教程过一遍? 不必。本系列 01~06 章覆盖了官方教程的核心内容,且全部用前端类比讲解,效率更高。官方教程可作为查漏补缺。

Q:代码看不懂是正常的吗? 前两周非常正常。这个项目有 1100+ 个 Dart 文件,第 1 周的目标是「能读懂」,不是「能全懂」。按路线图推进,第 3 周会突然通畅。

Q:可以直接跳到 10-页面开发实战 照着抄吗? 可以,但你会抄得不明所以,遇到报错无法排查。建议至少先过 01、02、08。

Q:练习一定要做吗?03~06 的练习强烈建议做——这些知识项目里没有现成参照物,只看不练等于没学。07~17 的练习可以用「读现有代码 + 跑现有测试」代替。


下一步 ​

→ 01 · Dart 语言基础