当前位置: 首页 > news >正文

深入解析:Flutter 项目结构该如何设计,才能支撑长期迭代

深入解析:Flutter 项目结构该如何设计,才能支撑长期迭代

网罗开发(小红书、快手、视频号同名)

大家好,我是展菲,目前在上市企业从事人工智能方案研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端制作、鸿蒙构建、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,首要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特殊关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告为读者提供有深度、有实用价值的技术洞察与分析。就是,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标

展菲:您的前沿技术领航员
大家好,我是展菲!
全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技巧进阶之路畅通无阻。
行业趋势的探讨,随时畅所欲言。就是 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还
最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!


文章目录

    • 前言
    • 常见 Flutter 工程结构对比
    • 页面级和业务级模块怎么划分
    • 可扩展的目录规范
    • 实际项目演进中的取舍
    • 总结

前言

很多 Flutter 项目一开始目录挺整齐,按「页面」「模型」「服务」一分,看起来挺好维护。可随着机制越加越多,改一处要动好几个文件夹、新人看半天不知道从哪下手、加个新需求总怕踩到老代码的雷。本质上是结构没按「长期迭代」来设计,只满足了「当下能跑」。要支撑长期迭代,就得在目录划分、模块边界和扩展规范上想清楚,让每个改动都有明确归属,新人也能按图索骥。

下面从常见结构对比、页面级和业务级怎么切、可扩展的目录规范、以及实际演进中的取舍几方面说一下。

常见 Flutter 项目结构对比

最常见的有两种思路:按「类型」分(type-first)和按「功能/业务」分(feature-first)。

按类型分,就是大家熟悉的 lib/models/views/services/utils/ 这种。所有模型放一起、所有页面放一起、所有接口放一起。好处是刚上手简单,找「所有接口」或「所有页面」很快。问题在于:一个业务(比如「订单」)的模型、页面、接口、状态会散在四个目录里,改一个需求要到处跳,职责也容易混——services 里既有订单接口又有用户接口,时间一长就变成大杂烩,新人很难判断「这段逻辑该放哪」。

按功能/业务分(Feature First),则是按业务域或功能块建目录,每个功能块里再放自己的页面、模型、接口、状态。例如 lib/features/order/lib/features/user/,每个 feature 下面再分 screens/widgets/models/services/ 等。这样「订单相关」的改动基本都在 order 下完成,边界清晰,新人接手也容易:先找 feature,再在 feature 里找具体文件。代价是前期要定好「哪些算一个 feature」,避免 feature 划分过细或过粗。

实际项目里,往往不会非此即彼:核心、会长期演进的业务用 Feature First真正全局的通用能力(如网络封装、路由、通用组件)单独抽成 shared 或 core,这样既避免「全按类型」导致的扩散,也避免「全按 feature」导致公共层缺失。

页面级和业务级模块怎么划分

「模块」可以按粒度拆成两种:页面级和业务级。

页面级以「一个或一组相关页面」为单位。比如「订单列表」「订单详情」「订单创建」算一个订单模块,里面主要是 UI、页面状态和该页用到的接口。适合功能相对独立、复用面不大的场景。划分时建议:一个模块一个目录,里面再按 screens/widgets/providers/bloc/ 等分层,避免一个文件上千行。

业务级比页面大一层,是「一整块业务」:订单从列表、详情、创建、支付、售后都算订单业务,可能跨多个页面、甚至多个 Tab。业务级模块里会包含多个页面级子模块,以及该业务共用的模型、领域逻辑、接口。划分业务级的意义在于:把「会一起变、一起发版」的东西收拢,减少跨模块的随意依赖。比如订单和商品是两条业务线,订单模块可以依赖「商品」的少量接口或模型,但不要反过来让订单逻辑散进商品模块。

实践中:先按业务级划出几个大目录(如 order、user、product),再在业务内部按页面或子功能划子目录。这样既不会一上来就几十个平级目录,也不会所有代码挤在少数几个文件夹里。

可扩展的目录规范

要支撑长期迭代,目录不能只满足「现在」,还要约定「以后怎么加」。建议定几条简单规范:

第一,统一命名和层级。例如每个 feature 下都允许有 screens/widgets/models/services/(或你项目用的分层),新增时只在这几类里加,不随意在 feature 根目录堆新名字。这样任何人一看就知道「新页面放 screens,新接口放 services」。

第二,公共能力单独成层。如 lib/core/lib/shared/ 放网络、路由、存储、通用 UI 组件、常量等。feature 只依赖 core/shared,不互相依赖;core 不依赖具体 feature。这样以后加新 feature 或换掉某个业务,不会牵一发动全身。

第三,约定「入口」。每个 feature 尽量有一个 index.dart 或明确入口文件,对外只 export 需要被路由或其它模块引用的部分,内部实现细节不暴露。这样依赖关系清晰,重构时也容易缩小影响面。

第四,文档化。在项目根目录或 lib/ 下放一个简单的 STRUCTURE.md,说明「业务模块有哪些、公共层放什么、新加一个 feature 要建哪些目录、命名约定」。新人按文档操作即可,减少「随便建个文件夹」的随意性。

一个可参考的目录示例(按上述规范收敛后)许可长这样:

lib/
├── core/                    # 公共层,被各 feature 依赖
│   ├── network/
│   ├── router/
│   ├── storage/
│   └── widgets/             # 通用按钮、弹窗等
├── features/
│   ├── order/
│   │   ├── screens/         # 订单列表、详情、创建等页
│   │   ├── widgets/         # 订单相关卡片、表单等
│   │   ├── models/
│   │   ├── services/
│   │   └── index.dart       # 只 export 路由需要的 Page、对外模型
│   ├── user/
│   │   ├── screens/
│   │   ├── widgets/
│   │   ├── models/
│   │   ├── services/
│   │   └── index.dart
│   └── product/
│       └── ...
└── app.dart                 # 入口,注册路由、主题等

解析:core 里不放业务逻辑,只放「大家都要用」的能力,这样新加或替换某个 feature 时,不会动到 core。每个 feature 内部结构一致(screens/widgets/models/services),新人加「订单下的新页」就知道去 order/screens/ 新建文件。index.dart 只对外暴露路由用到的页面和少量对外模型,避免其它模块直接 import 'order/xxx/internal.dart',以后改内部实现不会波及全局。按这种约定扩展,长期迭代时改动的范围更容易控制。

实际项目演进中的取舍

真实项目里,很少能从零就按「理想结构」来,多半是边做边收拢。

初期:功能少、人少,用类型分(models/views/services)就能跑。这时不必强行上 Feature First,但可以约定:新增功能时,尽量在一个「功能子目录」下集中放(例如 views/order/services/order/),为以后拆成独立 feature 留余地。

中期:功能多了、改一处动多处的情况开始出现,就能够选 1~2 个最核心、最常改的业务,先拆成 feature 目录,把相关页面、模型、接口都迁进去。其它暂时保持原样,用「新代码按新结构、老代码逐步迁」的方式演进,避免一次性大重构。

长期:核心业务都进 feature,公共能力稳定在 core/shared,再配合「入口 export」和依赖方向约定(feature 不互相依赖),就能比较稳地支撑长期迭代。遇到「这段到底算哪个 feature」的争议,以「谁改得多、谁负责」为准来归属,再慢慢用边界清晰化。

总结

Flutter 工程要支撑长期迭代,结构上建议:用 Feature First 收拢业务,用 core/shared 收拢公共能力;区分清楚页面级和业务级模块,先按业务划大目录再在内部按页面或子功能细分;并约定好目录层级、命名、入口和依赖方向,再配一份简短的结构说明文档。这样初期不会过度设计,后期也有清晰的扩展路径,改起来敢动、新人接手成本也会低很多。

http://www.jsqmd.com/news/645064/

相关文章:

  • 文档密码破解工具
  • 算法训练营第二天| 27.移除元素
  • 探索前沿技术趋势:2023年最值得关注的五大创新领域
  • C语言的循环语句
  • netDxf终极指南:.NET开发者的CAD文件处理神器
  • SAP BSP网页端开发实战:从SE80到MVC架构的完整指南
  • 无实体公司在美国如何雇人?一文读懂Safeguard Global名义雇主EOR服务 - 品牌2026
  • LIN总线开发避坑指南:用LDF Tool处理NAD分配与信号编码的5个关键细节
  • 企业智能体安全管理:从开源探索到企业级落地的必经之路 - 品牌2026
  • 高效数据处理 | 利用EXCEL插件实现度分秒与弧度、度的快速互转
  • 胡桃工具箱终极指南:免费开源原神助手如何提升你的游戏体验
  • 2025届必备的降AI率方案实际效果
  • VC++ 打造小型HTTP服务器
  • 终极指南:如何用novideo_srgb实现硬件级显示器色彩校准,解决宽色域显示器色彩过饱和问题
  • GetQzonehistory:你的QQ空间记忆守护者,永久保存青春时光
  • DETR模型训练AP=0?别慌!手把手教你排查自定义数据集常见问题
  • linux启动关闭java程序
  • GD32F103实战指南(3)——从零搭建Keil工程模板
  • 告别Windows系统管理烦恼:WinUtil一站式解决方案指南
  • 打造个人AI助手:通义千问2.5-7B+WebUI,免费商用全教程
  • 2026年旅游管理论文降AI工具推荐:市场调研和旅游策略部分 - 还在做实验的师兄
  • 无实体公司在巴西如何雇人?一文读懂Safeguard Global名义雇主EOR服务 - 品牌2026
  • 保姆级教程:用Python脚本将Cornell抓取数据集PCD文件批量转成TIFF(附避坑指南)
  • Ozon订单同步设置教程:新ERP对接与数据迁移全流程! - 跨境小媛
  • Termux安卓设备通过内网穿透搭建SFTP服务器实现跨设备文件共享
  • 如何快速部署OPC UA Client:面向开发者的完整配置教程
  • 2026实验室水质检测仪精选:COD氨氮总磷总氮检测仪口碑推荐 - 品牌推荐大师
  • 深度解析MOFA:5个核心优势掌握多组学因子分析
  • Verilog实战:用全加器搭建进位保存加法器(CSA)的完整流程
  • Midjourney提示词实战:从零到商业级插画的5个关键步骤