在很多 Flutter 项目刚启动的时候,架构往往不是最先被讨论的问题,通常客户端的架构在初始阶段往往被轻视。
页面能跑、功能能用、交互看起来也没什么问题,似乎一切都在一个“差不多”的状态里。但当项目进入多人协作、功能逐渐增多、开始覆盖不同平台之后,问题往往会以一些并不温和的方式出现。
回头看我自己经历过的几个 Flutter 项目,真正让我意识到“Plugin 基础建设”这件事的重要性,并不是因为某一次写得不顺,而是因为后期维护的代价实在太高。
真实工程中,为什么对 Plugin 做明确分级。
为什么做 Plugin 分级
曾经和别人讨论过一个问题,如果不考虑任何设计模式,不使用任何推荐的项目结构,直接将所有代码放在一个类中是否可以运行项目——答案是当然可以,只要你不担心在一个风和日丽的下午老板突然过来打爆你的头。
Flutter 的优势很明显:跨平台、高效率、学习曲线友好,视图搭建迅速等。
但这些优势,在项目规模变大之后,也会反过来放大一些风险。其中最典型的一点是:
平台差异并不会因为 Flutter 而消失。
在涉及原生能力的场景中,比如蓝牙、WiFi、文件系统、系统权限管理等,不同平台之间的实现差异是客观存在的。如果在早期没有通过分包或插件做逻辑隔离,这些差异很容易通过 if platform()这样的判定“顺手”写进业务层。
短期看,这样做确实很便捷;
但随着平台变多、功能复杂,这些差异就会迅速演变成维护噩梦,甚至演化为 P0 问题。
Plugin 的分级并不是为了架构好看,而是为了回答一个更现实的问题:
复杂度到底应该被放在哪里?
如果不主动为它准备一个容器,它迟早会流向业务层给各个功能模块带来负担逐渐变为一坨人人躲避的狮山,在未清晰了解业务及历史包袱前不要轻易动狮山,它一定能埋住每个自认为精明的人,如同罗马不是一日建成一般一坨狮山也是充满了各种包袱,解决他的最好方式是在一开始就应该尽可能避免后续的明显不合理堆砌。
Plugin 分级的常见思路
在实际项目中,通常根据平台特性 & 业务形态对 Plugin 做分级。
这种分级并不是绝对的,但优先级是明确的。
P0:平台能力分级 —— 最应重视
Flutter 在 UI 层非常强,但在原生能力调用上天然存在短板。
只要涉及以下场景:
- 蓝牙、WiFi 等硬件能力
- 文件存储、系统权限
- 与平台生命周期强相关的能力
就不可避免地需要和原生代码打交道。
如果这些逻辑被直接写进业务层,问题往往不是“现在能不能跑”,而是未来还能不能维护。
一次平台改动,就可能牵动大量业务代码,甚至直接引发线上事故。
因此这一层次的抽离往往很关键,通常有以下几个基本要素 :
- 所有平台差异,只存在于 plugin 内部
- 对业务层暴露的,只是统一接口
- 业务层永远不需要关心当前运行在哪个平台
目标只有一个:
通过模块化的划分,把平台复杂度进行封装,只对业务暴露接口能力
这是整个架构中,优先级最高、也最不能妥协的一层。
P1:视图公共组件 —— 越早越好
很多项目 UI 层的问题,在一开始并不容易显现。
项目初期,如果没有明确的开发要求,大家往往各自为战:颜色随手写、样式临时配、弹窗任意调用(毕竟潜意识都觉得 UI 并没有什么设计模式)。短期内看不出太大问题并且开发效率还不差,但当进入多人协作、持续迭代阶段,这些“一时之爽”会迅速堆积成不可忽视的技术债。
在界面开发初期,应尽早纳入视图组件层的建设范围:
- 基础色值与文本样式
- 通用按钮、输入组件
- 弹窗、Toast、对话框
- 路由与页面容器的统一管理
这一层的风险在于:
它不是马上爆炸的,但一旦失控,影响范围几乎是全部
等你真正意识到样式、图标、交互已经出现系统性差异时,往往已经很难在不付出巨大成本的情况下完成重构。
从经验来看,这是一个典型的 P1 问题,但后果接近 P0。
P1:业务域 —— 模块 Owner
当项目开始拆分模块、多人并行开发时,业务层的结构清晰度会直接影响协作效率。
像登录、用户信息、网络请求、设备管理这类由专人长期维护的功能,如果全部堆在一个业务层里,很容易出现职责不清、改动互相影响的问题。
将这类功能按业务域拆分为独立 Plugin,可以带来几个明显收益:
- 职责边界更清晰
- 减少无关代码的改动影响
- 更利于并行开发与长期维护
需要强调的是,这一层并不是“拆得越细越好”,而是拆到责任明确为止。
P2:通用工具 —— 提高复用
还有一类 Plugin,或者说 Package 通常优先级略低,但迟早需要面对:
- 日志系统
- 全局通用的加解密策略
- 一些跨模块复用的工具方法
这类代码个人更倾向于以 Dart Package 的形式维护:
- 独立版本,尽可能不依赖三方插件
- 明确使用边界(根据项目及团队情况制定)
- 避免工具方法无限膨胀
这一层往往不会成为项目初期的瓶颈,但如果长期忽视,后期同样会成为技术债的集中区。
简要的分级总结
如果从宏观角度看,一种接受度较高的分级维度是:
- Platform Plugin(P0) :控制平台差异,避免业务层 P0
- Widget / UI Plugin(P1) :控制一致性,避免不可回收的样式债
- Domain Plugin(P1) :控制协作成本,明确业务责任
- Tools / Package(P2) :控制复用与技术债扩散
分级的目的,从来不是限制开发,而是让复杂度有序生长。
写在最后
通过一篇短文不可能一次性讲清楚 Flutter Plugin 架构分级。
在后续的《Flutter 架构日记》中,笔者将通过实践结合理论会分别展开不同的分级维度,结合真实项目中的取舍与踩坑经历,围绕以下几点展开学习讨论:
- 平台 Plugin 的设计边界
- UI 组件如何避免野蛮生长
- 业务域 Plugin 的拆分时机
- 通用工具层如何保持克制
架构从来不是一套固定答案,而是一连串在真实约束下不断的做选择,正是它的不唯一性造就了软件工程这门学科;