2、第一个嵌入式Flutter应用:创建项目、理解结构、运行到设备
好,咱们直接动手。这一章我会带你从零创建一个嵌入式Flutter项目,然后把它跑在真实的嵌入式设备上。你可能会觉得「不就是flutter create吗?」——嗯,没那么简单。嵌入式环境有它自己的脾气,咱们得摸清楚。
2.1 创建Flutter项目
先打开终端,找个干净的目录。我个人习惯把嵌入式项目统一放在 ~/embedded_flutter/ 下,方便管理。
flutter create --org com.embflutter --platforms=linux first_embedded_app
这里注意几个关键点:
--platforms=linux:嵌入式Flutter目前主要跑在Linux上,所以只生成Linux平台代码。别加android或ios,否则编译时会多出很多不必要的依赖。--org:包名,我习惯用com.embflutter,方便区分嵌入式项目。
创建完成后,你会看到这样的目录结构:
first_embedded_app/
├── lib/
│ └── main.dart
├── linux/
│ ├── CMakeLists.txt
│ ├── flutter/
│ │ └── CMakeLists.txt
│ └── main.cc
├── test/
├── pubspec.yaml
└── ...
嗯,这里要特别说一下 linux/ 目录。它里面藏着嵌入式设备启动Flutter引擎的C++入口。说白了,你的Dart代码最终是通过这个C++壳子跑起来的。
核心理解:嵌入式Flutter应用 = Dart UI层 + C++引擎层。linux/main.cc就是引擎的启动入口,一般不需要改,但出了问题排查时你得知道它在哪。
2.2 理解项目结构
咱们挑几个关键文件说说:
| 文件/目录 | 作用 | 嵌入式特别说明 |
|---|---|---|
| lib/main.dart | Dart入口,你的UI代码 | 和移动端一样,但要注意内存 |
| linux/main.cc | C++入口,启动Flutter引擎 | 嵌入式设备可能需修改窗口大小 |
| linux/CMakeLists.txt | 构建配置 | 嵌入式交叉编译时需改这里 |
| pubspec.yaml | 依赖管理 | 嵌入式慎用大包,比如video_player |
我记得第一次做嵌入式项目时,盯着 linux/main.cc 看了半天。里面有个 flutter::DartProject 的初始化,我当时以为要改很多,其实大部分场景下保持默认就行。但有一个参数你可能会用到——窗口尺寸:
// linux/main.cc 中
flutter::ViewProperties view_properties;
view_properties.width = 800;
view_properties.height = 480; // 嵌入式屏幕常见分辨率
如果你的设备是7寸屏、10寸屏,记得在这里改。我踩过这个坑——默认1024x768,结果在800x480的屏上只显示了一半。
2.3 运行到嵌入式设备
好,项目创建好了,结构也懂了。接下来是最激动人心的部分——跑起来。
嵌入式设备和手机不一样,没有USB调试那一套。你得先确定目标设备的架构。常见的有:
- armv7l:老一点的ARM板子,比如树莓派3B
- aarch64:64位ARM,比如树莓派4B、RK3588
- x86_64:少数工控机用这个
假设你用的是树莓派4B(aarch64),编译命令是这样的:
flutter build linux --release --target-arch=arm64
然后你会得到一个 build/linux/arm64/release/bundle/ 目录。把这个目录整个拷贝到嵌入式设备上,比如用scp:
scp -r build/linux/arm64/release/bundle/ pi@192.168.1.100:~/my_app/
在设备上执行:
cd ~/my_app/
./first_embedded_app
如果一切顺利,屏幕上会出现Flutter默认的计数器应用。嗯,那一刻的感觉还是很爽的。
我曾经遇到的坑:第一次运行时,设备上缺少libflutter_engine.so。后来发现是编译时没有把引擎库打包进去。解决方案是在CMakeLists.txt里加上 flutter_engine 的链接路径。如果你也遇到类似问题,先检查bundle目录里有没有 libflutter_engine.so。
2.4 热重载与热重启在嵌入式上的表现
这是很多人关心的问题。在手机上,热重载几乎是秒级的。但在嵌入式设备上,情况有点不一样。
首先,嵌入式Flutter 支持热重载,但前提是你得用debug模式运行:
flutter run -d linux --target-arch=arm64
然后你会看到类似这样的输出:
Flutter run key commands.
r Hot reload.
R Hot restart.
h List all available interactive commands.
按 r 触发热重载。你会发现:
- 热重载速度:在树莓派4B上,大约2-5秒。比手机慢,但还能接受。
- 热重启速度:大约10-15秒。因为要重新初始化引擎。
- 首次启动:最慢,可能要30秒以上,因为要加载引擎库。
我的建议:嵌入式开发时,尽量用热重载。热重启太慢了,每次等得心焦。我一般改UI逻辑时用热重载,改状态管理或初始化代码时才用热重启。
为什么会这样?说白了,嵌入式设备的CPU和内存都有限。树莓派4B的4核Cortex-A72,跟手机上的骁龙8系比,差距还是明显的。所以你要有心理准备——热重载不是秒级的,但比重新编译快多了。
另外,有个小技巧:如果你改了 pubspec.yaml 添加了依赖,必须 flutter pub get 然后热重启,热重载不管用。我刚开始不知道,每次改了依赖就按 r,结果半天没反应,还以为是设备坏了。
2.5 本章小结
这一章我们做了三件事:创建项目、理解结构、跑起来。你可能会觉得内容不多,但嵌入式Flutter的入门门槛就在这里——环境搭好了,后面就顺了。
下一章我们会深入嵌入式设备的硬件交互,比如GPIO、I2C这些。到时候你会发现,Flutter不只是做UI,还能直接控制硬件。嗯,那才是嵌入式开发的真正乐趣所在。