我十几个项目都是这套Flutter 快速开发框架,今天开源了,从此你只用关心业务了

不知道你有没有过这种"既视感":每次开一个新 Flutter 项目,都得把那一套"祖传代码"再复制粘贴一遍。

配网络请求 Dio、设路由、封装几个通用 Widget、搞个状态管理......一套流程下来,半天过去了,真正的业务代码,一行都还没写。这感觉,就像你准备做一桌满汉全席,结果光是淘米、洗菜、磨刀就花了大半天,累得够呛。

这堆重复劳动,我称之为"开发税"------每个项目都得交,还不得不交。

后来我带的团队项目多了,这个问题就更严重了。A 同学封装的网络请求,B 同学用不惯;C 同学写的组件,D 同学那边又改一版。代码规范?不存在的。效率?全看个人手感。

不行,这税得想办法给它"免"了。

于是,我花了点时间,沉淀了一套自己的 Flutter 快速开发框架。今天,我就把这套思路掰开揉碎了分享给你,让你也能搭一套自己的"轮子",告别重复劳动,把精力真正聚焦在业务上

一、从各自为战到统一思想:我的"翻车"与顿悟

一开始,我的想法很简单:把常用的工具类、网络请求封装一下,打个包不就完事了?

结果呢?第一个项目还行,第二个项目开始魔改,到了第三个,已经跟第一版亲妈都不认识了。究其原因,就是缺少一个核心设计思想

后来我才悟了,一个好的框架,不是功能的堆砌,而是规则的建立 。它的灵魂就八个字:"约定优于配置"(Convention over Configuration)

啥意思?

就是说,框架要替你"规定"好,什么文件放哪里、什么模块叫什么名。比如,只要你把一个页面放在 features/ 目录下,框架就应该能自动帮你注册好路由。你不用去手动配置,框架通过"约定"就帮你搞定了。

基于这个思想,整个框架的设计就清晰了:

  • 高内聚,低耦合:每个模块像乐高积木,只干一件事,可以随时替换。今天用 Dio,明天想换 http,拔掉重插就行。
  • 插件化:功能即插件。需要地图就加个地图插件,不需要就不加,保持核心的轻量。
  • 只关心业务:把网络、缓存、路由这些脏活累活全藏在底层,暴露给业务开发的,是极其简单的接口。

二、蓝图在手,天下我有:框架的整体架构

光有理念不行,得有张蓝图。下面这张图,就是我打磨出来的项目架构,清晰明了,新手照着搭都不会错。

我给你翻译一下:

  • core/ (核心能力) :这是框架的发动机。网络、路由、状态管理、缓存、日志这些"脏活累活",全部扔这里。业务开发者原则上不应该直接修改这里面的代码。
  • common/ (通用资产):这是团队的"共享工具箱"。通用的按钮、加载框、工具类、主题样式,都在这儿。
  • features/ (业务模块):这才是我们每天打交道的主战场。每个功能模块(比如登录、首页、设置)都是一个独立的文件夹,高内聚。
  • generated/ (自动生成):所有由工具自动生成的文件,比如路由表,都放这。和手写代码隔离,非常清爽。

这套结构,就像一个城市的规划:主干道(core)、公共设施(common)、各个小区(features),分工明确,井井有条。

三、庖丁解牛:几个关键模块我是怎么设计的

蓝图有了,我们来聊聊几个关键"零件"是怎么打磨的。

1. 路由系统:告别手写路由表

  • 我踩过的坑 :一开始用官方的 MaterialPageRoute,每次跳转都手写一大坨。页面多了,参数传递能把人逼疯,简直是"屎山"的重灾区。
  • 我的理解:路由应该像"查字典",我告诉你去哪(命名路由),你就自动帮我带路,别让我操心怎么走。
  • 最终方案 :采用注解 + 代码生成。我强烈推荐 auto_route 这个库。

你只需要在页面类上加个注解:

dart 复制代码
@RoutePage()
class LoginPage extends StatelessWidget { ... }

然后跑个命令,它就会自动生成带参数的、类型安全的路由方法。用起来有多爽?

dart 复制代码
// 告别 "Navigator.pushNamed('/login', arguments: ...)"
// 拥抱类型安全
AppNavigator.push(LoginRoute(userName: "LaoG"));

跳转、传参、返回,一个方法搞定,优雅,太优雅了!

2. 网络请求:建一个"中央厨房"

  • 我踩过的坑 :每个页面都自己创建一个 Dio 实例,到处都是 try-catch。后端一说 token 失效要重新登录,我就得去几十个文件里改代码,改到最后,自己都不知道改没改全。
  • 我的理解:网络请求是典型的"横切关注点",它需要一个统一的"哨兵"或"网关"来处理公共逻辑。
  • 最终方案 :封装一个全局单例的 Http 类,把 Dio 包在里面。重点是玩转拦截器(Interceptor)

我的拦截器链通常是这样的:

  1. 日志拦截器:Debug 环境下打印详细的请求、响应日志,甩锅(哦不,定位问题)必备。
  2. 请求头拦截器 :统一加上 Content-TypeToken 等。
  3. 响应拦截器 :在这里做统一的业务错误码处理。比如 code: 401 就直接弹窗提示并跳转到登录页,页面代码里根本不用关心这事儿!
  4. 错误拦截器:处理网络超时、DNS 解析失败等异常,给用户一个友好的提示。

这样一来,业务代码里的网络请求就变得极其纯粹:

dart 复制代码
// 业务层只需要这样调用,完全不关心 Token 和错误处理
final user = await Http.instance.get('/api/user/1');

3. 状态管理:给你的页面装个"大脑"

  • 我踩过的坑 :从 setStateProvider,一开始觉得挺好,但业务一复杂,UI 和业务逻辑就搅在一起,跟一团浆糊似的。状态满天飞,想找个 bug,得从 UI 代码里一点点往回捋。
  • 我的理解 :UI 应该是个"傻子",它只负责展示数据和发送指令。真正的思考和数据处理,应该交给一个专门的"大脑"------ViewModel
  • 最终方案 :推荐使用 Riverpod + MVVM 模式。

Riverpod 的好处在于它天生的依赖注入和更清晰的生命周期管理,非常适合解耦。我会创建一个 BaseViewModel,内置几种通用状态:

dart 复制代码
enum ViewState { idle, loading, error, empty }

abstract class BaseViewModel extends StateNotifier<ViewState> {
  // ... 内置加载、错误处理等通用方法 ...
  Future<void> safeAction(Future<void> Function() action) async {
    state = ViewState.loading;
    try {
      await action();
      state = ViewState.idle;
    } catch (e) {
      state = ViewState.error;
    }
  }
}

每个页面的 ViewModel 都继承它,天生就拥有了加载中、错误、空页面的状态管理能力。

四、锦上添花:用命令行工具解放生产力

框架搭好了,怎么让它用起来更爽?答案是:命令行工具

我用的是 mason 这个库,它可以让你创建自己的代码模板。比如,我想创建一个新的登录页面,只需要在终端敲一行命令,当然我的做法是直接集成到 vscode 插件中,这样对着 feature 右键,就可以创建各种,何止是页面呀,想啥是啥:

bash 复制代码
mason make page login

然后,mason 就会自动帮我创建好:

bash 复制代码
features/
└── login/
    ├── view/login_page.dart
    ├── view_model/login_vm.dart
    └── widgets/

ViewModel 的继承、页面的基础结构都写好了!这感觉,就像从手动挡换到了自动挡,谁用谁知道。

落地实践建议

看到这里,你可能有点心动,但又觉得工程量太大。别慌,罗马不是一天建成的。

  1. 从封装一个模块开始:先别急着搭整个架子。在你下个项目中,先尝试只封装一个完美的网络请求模块。
  2. 建立你的 Starter 项目 :把你的最佳实践沉淀到一个 GitHub 仓库里,创建一个 flutter-starter-template。以后开新项目,直接 git clone 就行。
  3. 团队布道:如果你在团队里,把这套东西分享给同事,形成规范。统一的规范,是提升团队整体效率的大杀器。

好了,今天就先聊到这。框架不是目的,效率才是。希望这套思路能帮你摆脱"开发税",把更多的时间和才华,投入到创造真正有价值的业务功能中去。

延伸阅读推荐:

  1. Riverpod 官网 : riverpod.dev/ (状态管理的未来,值得深入研究)
  2. auto_route 官方文档 : pub.dev/packages/au... (感受一下注解式路由的魅力)
相关推荐
cos1 小时前
从像素到粒子:p5.js 图像转动态粒子的设计与实现
前端·javascript·webgl
COSMOS_*2 小时前
2025最新版 Go语言&Goland 专业安装及配置(超详细)
开发语言·后端·golang·go
mCell2 小时前
那台榨汁机,竟是哈希表祖师爷?
后端·安全·go
ChinaRainbowSea2 小时前
用户中心——比如:腾讯的QQ账号可以登录到很多应用当中 02
java·服务器·spring boot·后端·mysql·mybatis
追逐时光者3 小时前
精选 10 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
造糖主义3 小时前
vue-el-upload上传组件自定义删除-预览按钮遮罩层,不受原有的上传打开文件夹
前端·javascript·vue.js
小猫会后空翻4 小时前
XSS相关理解
前端·xss
要开心吖ZSH4 小时前
Spring Boot 自动配置:从 spring.factories 到 AutoConfiguration.imports 的演变
spring boot·后端·spring
神仙别闹5 小时前
基于ASP.NET+SQL Server的网站登录注册功能设计与实现
后端·asp.net