本方案遵循 “从纯净开始,按需组合” 的核心原则,旨在构建一个专注、灵活、可维护的Subsonic客户端。它避免了引入庞大、僵化的“全家桶”脚手架,确保每一项技术决策都直接回应具体的业务需求。
从
flutter create开始,像搭积木一样,每遇到一个明确、具体的需求,才引入解决该问题的最佳库。
-
第0步:纯净起点 (Week 1)
- 行动:使用
flutter create --platforms=android,ios,desktop创建项目。 - 目标:建立最干净的项目基底。此时,
pubspec.yaml中只有Flutter SDK本身。
- 行动:使用
-
第1步:UI骨架与导航 (Week 1-2)
- 需求:绘制基础页面,并能在它们之间跳转。
- 行动:使用Flutter内置组件搭建页面。引入
go_router。 - 产出:一个能切换“首页”、“浏览”、“播放页”的静态App。
-
第2步:播放与网络核心 (Week 2-3)
- 需求:连接Subsonic服务器,并能播放音频。
- 行动:
- 引入
dio用于调用Subsonic RESTful API。 - 引入
just_audio(播放引擎)和audio_service(后台任务、锁屏控制)。这是最先确立的核心,应设计成独立的、与UI解耦的服务。
- 引入
- 产出:一个能从Subsonic服务器获取歌曲列表并播放的App。
-
第3步:数据缓存与状态管理 (Week 3-4)
- 需求:缓存浏览过的专辑/歌单,让收藏、播放记录能离线查看,并同步UI状态。
- 行动:
- 引入
hive。为Subsonic的实体(Album,Song)创建带@HiveType()注解的模型,用于本地持久化缓存。 - 当发现需要在多个Widget间共享播放状态(如当前歌曲、播放进度)时,引入
flutter_riverpod。
- 引入
- 产出:支持离线浏览、收藏,且UI能实时响应播放状态变化的App。
-
第4步:功能增强与优化 (Ongoing)
- 需求:歌词显示、动态主题、本地文件扫描等。
- 行动:真正地按需引入。例如,需要歌词时再评估并添加
flutter_lyric等库。 - 产出:功能逐步完善的成熟客户端。
| 模块 | 推荐库 | 核心理由 | 适用于你的Subsonic App |
|---|---|---|---|
| 网络 | Dio | 强大的拦截器、请求取消功能,适合与Subsonic API稳定通信。 | 所有数据来源的根基。 |
| 播放 | just_audio + audio_service |
黄金组合。前者处理解码,后者将播放器与UI/系统集成,实现后台播放。 | App的心脏,必须稳定、解耦。 |
| 本地存储 | Hive | 读写极快,API简单,完美匹配“缓存API响应”和“存储用户偏好”的核心场景。 | 比SQLite更轻量、直接,避免了为简单缓存设计复杂表结构。 |
| 状态管理 | Riverpod | 响应式、编译安全、优秀的依赖注入,能优雅地管理播放状态和异步数据流。 | 连接“播放服务”和“UI”的神经系统。 |
| 路由 | GoRouter | 声明式路由,完美支持深层链接、嵌套导航和平台原生过渡动画。 | 管理所有页面跳转的路线图。 |
- 数据流架构:采用 “网络层 -> 缓存层(Hive) -> 仓库层(Repository) -> 状态提供层(Riverpod) -> UI” 的清晰数据流。这确保了关注点分离,未来替换任何一层(如换用其他缓存方案)都代价极小。
- 缓存策略:
- 使用Subsonic API返回的
id作为Hive Box的Key。 - 在数据模型中加入
cacheTime字段,实现简单的缓存过期逻辑。 - 在Provider中实现 “缓存优先,网络兜底” 的智能数据获取逻辑。
- 使用Subsonic API返回的
- 播放器服务:将
just_audio和audio_service封装成独立的全局服务(如AudioPlayerService),只通过Riverpod Provider暴露其状态和控制接口,确保UI与播放逻辑完全解耦。 - 模型生成:同时使用
json_serializable(处理网络JSON)和hive_generator(生成Hive适配器),它们可以共存,极大提升开发效率。