AtomGit Flutter 鸿蒙客户端:零外部资源的应用打包策略
·

一个没有任何图片、音频、字体文件的 Flutter 应用——E-Brufen 的所有"资源"都是代码生成的。本文详解这一策略的设计理念、工程实践与收益量化。
一、"零资源"意味着什么?
1.1 传统 Flutter 应用的资源清单
一个典型的 Flutter 应用通常携带大量外部资源:
# 典型 Flutter 应用
flutter:
assets:
- assets/images/logo.png # 80 KB
- assets/images/onboarding1.png # 200 KB
- assets/images/onboarding2.png # 180 KB
- assets/images/bg_home.png # 350 KB
- assets/audio/rain.mp3 # 2.5 MB
- assets/audio/ocean.mp3 # 2.8 MB
- assets/fonts/custom.ttf # 1.2 MB
# ... 几十行
# 合计: 10-50 MB 的二进制资源
1.2 E-Brufen 的 pubspec.yaml
# E-Brufen
flutter:
uses-material-design: true
# 没有任何 assets 声明
# 没有任何 fonts 声明
★ Insight ─────────────────────────────────────uses-material-design: true只引入了 Material Icons 字体(约 2MB),这是 Flutter 框架自带的,不算我们的"资源"。真正的自定义资源——零。─────────────────────────────────────────────────
二、程序化生成矩阵
| 资源类型 | 生成脚本 | 产物 | 大小 | 算法核心 |
|---|---|---|---|---|
| 应用图标 | generate_icon.dart |
app_icon.png (512×512) | ~1 MB | 极坐标花瓣纹理 + PNG 手写编码器 |
| 雨声音效 | generate_audio.dart |
rain.wav (30s) | ~1.3 MB | 高通白噪声 + 双正弦包络 |
| 海浪音效 | generate_audio.dart |
ocean.wav (30s) | ~1.3 MB | 布朗噪声 + 双波相乘包络 |
| 篝火音效 | generate_audio.dart |
fire.wav (30s) | ~1.3 MB | 底噪 + 稀疏脉冲事件 |
| 森林音效 | generate_audio.dart |
forest.wav (30s) | ~1.3 MB | 中频噪声 + FM 鸟鸣 |
两个脚本替代了约 8-10 个二进制文件。
三、定量收益分析
3.1 Git 仓库体积
# 传统方式
git add assets/
git commit -m "add audio and image assets"
# → 仓库增加 ~7 MB
# E-Brufen 方式
git add generate_audio.dart generate_icon.dart
git commit -m "add asset generator scripts"
# → 仓库增加 ~20 KB(两个 .dart 文件)
仓库体积缩小约 350 倍。 不需要 Git LFS、不需要处理二进制文件的 merge conflict。
3.2 构建可复现性
# 在任何机器上,运行相同脚本得到完全相同的输出
dart run generate_icon.dart # 输出: 相同 MD5 的 app_icon.png
dart run generate_audio.dart # 输出: 相同 MD5 的 rain.wav
这是 CI/CD 中"可复现构建"的最佳实践——不需要管理"设计师改了图但没同步到 Git"的问题。
3.3 参数化定制
// 修改一行参数 → 生成不同风格
const iconSize = 1024; // 改为更高分辨率
const audioDuration = 60; // 改为 60 秒
const sampleRate = 44100; // 改为高采样率
const petalCount = 5; // 三瓣花改为五瓣花
不需要设计师重新出图——改代码即可。这对 A/B 测试和快速迭代非常有用。
四、构建流程集成
#!/bin/bash
# 完整构建脚本
echo "Generating assets..."
dart run generate_icon.dart
dart run generate_audio.dart
echo "Building HAP..."
flutter build hap --release
echo "Done!"
或使用 Makefile:
.PHONY: generate build clean
generate:
@dart run generate_icon.dart
@dart run generate_audio.dart
build: generate
@flutter build hap --release
clean:
@flutter clean
@rm -f ohos/AppScope/resources/base/media/app_icon.png
@rm -f assets/audio/*.wav
五、适用边界
这个策略不是万能药。明确其适用范围:
| 场景 | 适合程序化生成? | 原因 |
|---|---|---|
| 几何图案图标 | ✅ 适合 | 数学函数天然擅长 |
| 自然音效(噪声类) | ✅ 适合 | 信号处理直接合成 |
| 照片级图像 | ❌ 不适合 | 需要物理世界采样 |
| 人类语音 | ❌ 不适合 | 需要录制或 TTS |
| 复杂音乐 | 部分适合 | MIDI 合成可行但难度高 |
| UI 插画 | 部分适合 | 可用 SVG path 代码化 |
六、哲学:代码即资源
E-Brufen 的零资源策略背后是一种编程哲学:
如果一段资源可以用 200 行确定性代码生成,它就不应该作为 2MB 的二进制文件被存储。
代码比二进制文件的优势:
- 可 diff:
git diff能看到参数变化 - 可 review:代码审查可以检查生成逻辑
- 可测试:可以为生成算法写单元测试
- 可版本化:参数变化跟随代码版本
- 可移植:不依赖特定工具(Photoshop、Audacity)
上一篇:Zlib 压缩算法的手写实现
下一篇:响应式问候语
作者简介:E-Brufen Dev,Flutter & 鸿蒙开发者。零资源策略是 E-Brufen 项目最具特色的工程决策之一。
更多推荐



所有评论(0)