Flutter 把第三方 UI 库渐进迁回 Material 3:组件映射总表 + 四批次替换实战

Flutter 把第三方 UI 库渐进迁回 Material 3:组件映射总表 + 四批次替换实战

作者:FungLeo | 适用:Flutter 3.x / Material 3

场景:早期引入的第三方 UI 库不太稳,想换回原生 M3,又不敢一刀切。

本文要点

  • 第三方 UI 库不是不能引,但 0.x 版本 + 样式钩子少,长期项目迟早撞墙
  • 迁移铁律:先有替代品,再替换,绝不裸删(裸删 = 把设计决策塞进体力活,必乱)
  • 动手前 grep 摸底 + 产出组件映射总表,把决策前置
  • 四批次按风险排序,高频组件反而靠后,每批可独立回滚
  • 移除依赖是最后一步:grep 扫全量源码确认零残留,完整重建验证

前言

前文 B01 从 0 搭品牌主题四件套 把主题层搭好了,这篇聊聊怎么把第三方 UI 库的组件一点点换上去。

我们项目早期引了一套第三方 UI 库(TDesign Flutter,0.2.x 版本)。当时想法很朴素:现成组件拿来就用,省时间,何必造轮子。

一开始确实爽。但用了一阵,问题陆续冒出来了:

  • 某些组件在 Android 上白屏,换机型又好了,难稳定复现;
  • 小版本之间 API 会变,升一次得改一圈调用;
  • 视觉细节跟设计稿对不齐,样式没暴露出来,改不动;
  • 最要命的,出问题只能等上游修,自己插不上手。

那段时间挺纠结,一开始想"再忍忍"。后来算了笔账------每月因这套库损耗的排查时间,其实已经超过一次性迁移成本了。于是决定:整体迁回 Material 3 原生 + 自研公共组件

但"换 UI 底层"最忌一次性全改。我见过有团队开个大分支 all in,改三周,合主干时冲突炸裂,测试还没法测------整个 App 都变了,根本不知道该重点回归哪儿。所以我用渐进式四批次替换。这篇把整个过程完整记一下。

第一步:先 grep 摸底,把家底摸清楚

动手前,先搞清楚要改多少东西。别凭感觉,凭感觉估的工作量一般能差三倍。

我的做法是直接 grep 全项目,统计每个三方组件出现次数:

sh 复制代码
# 统计每个组件出现次数,从多到少排序
grep -rho "TD[A-Za-z]*" lib/ | sort | uniq -c | sort -rn

# 看某个组件具体分布在哪些文件,加 -l
grep -rl "TDButton" lib/

跑出来大概是这么个分布:

sh 复制代码
🔴 TDButton(~15 处)、TDToast(~20 处)  # 高频,影响面最广
🟡 TDTextarea(3)、TDPicker(2)、TDStepper(2)、TDNavBar(1)  # 中频
🟢 TDIcons(~20 个不同图标名)           # 纯图标,最好换

这张表出来,心里就有底了:真正麻烦的不是数量,而是高频组件牵一发动全身TDToast 二十处散在各种异步回调里,改错一个可能就是线上一个静默失败。据此排了替换优先级,并产出一张组件映射总表。

第二步:产出组件映射总表

这一步我强烈建议做,且写成文档存下来,别只放脑子里。因为迁移不是一天干完的,中间会被别的需求打断,三天后回来早忘了 TDPicker 换成啥。多人协作没这张表,两人会替换出两种写法,那还不如不迁。

表大概长这样(节选):

旧组件 M3 / 自研替代 备注
TDIcons.xxx Icons.xxx 一一对应,最简单
TDButton(主按钮) FilledButton 圆角走 B01 的主题覆写
TDButton(次按钮) OutlinedButton / TextButton 按视觉层级选
TDToast 自研 AppToast 统一入口,后续 B04 会展开讲公共组件库
TDAlertDialog 自研 AppDialog.confirm 收敛掉 builder 样板
TDNavBar AppBar 主题里已统一样式
TDTextarea 自研 AppTextarea 带字数计数浮层
TDPicker showModalBottomSheet + 自绘 M3 无直接对应
TDStepper 自绘 M3 无直接对应

映射表里有几个坑,提前说:

一是"一对多"。TDButton,第三方库常用一个组件加 type 参数搞定所有按钮形态;M3 拆成 FilledButton / OutlinedButton / TextButton 三个独立组件。所以你不能无脑替换,得一处一处看它原来是什么形态。这是整个迁移里最费眼力的部分。

二是"没有对应物"。 步进器、日期选择器这些,M3 没提供或形态不合适,只能自绘。这部分工作量最大,单独排批次,别混在常规替换里。

三是行为差异。 这个最阴险。比如三方 Toast 可能"自动排队、后一个等前一个消失",而你用 ScaffoldMessenger 自己实现的是"后一个直接顶掉前一个"。视觉上都是弹提示,但批量操作场景下表现完全不同。这种差异 flutter analyze 查不出,只能靠真机点。

第三步:先搭"替代品",再动手替换

这条我最想强调:不要边删边想新写法。

我一开始就是这么干的------删掉一个 TDToast,现场想"那我用什么呢",随手写了个 ScaffoldMessenger.of(context).showSnackBar(...)。改到第五处,发现前面四处样式、时长、位置全不一样,因为每次都是现场发挥。

正确顺序是:

  1. 先按 B01 把主题四件套搭好,让原生组件样式先对上设计稿;
  2. 再把公共组件抽出来(AppDialog / AppBottomSheet / AppSearchBar / AppToast,后续 B04 细讲);
  3. 放一个 preview 分支,专门做个测试页,把所有形态摆出来验一遍;
  4. 确认组件质量过关,再回主干逐页替换。

这样替换时你就是个"体力活工人",机械地把旧的换成新的,不需要动脑做设计决策。脑子越不需要动,出错概率越低,这活儿也才安心交给别人一起干。

第四步:四批次渐进替换

批次按风险排,不是按工作量:

批次 内容 风险
1 主题搭建 + 组件测试页
2 低风险:图标 Icons.xxx / AppToast / AppDialog
3 中风险:搜索栏 / 表单区块 / 底部操作栏
4 自绘:步进器、日期选择器等无直接 M3 对应的

这里有个反直觉的点:高频组件(Button / Toast)影响面最大,为什么反放在靠后批次?

因为影响面大,意味着一旦替代品有问题,波及页面也最多。你得先让替代品在小范围跑一段时间,确认没毛病,再拿它去铺二十个页面。反过来,先铺二十个页面再发现问题,你就得改二十遍。

每一批替换完,跑一遍静态检查再上真机:

sh 复制代码
# 静态检查,先把编译期和 lint 问题清掉
flutter analyze

# 真机跑一遍,重点看这一批涉及的页面
flutter run

关键是:单批可独立回滚。 每批单独提交、单独合并,哪批出问题 git revert 掉那个提交就行,不影响其他批次。渐进式最大价值不是改得快,是出事时退得起

第五步:彻底移除依赖

全量替换完成、确认无残留之后,才从 pubspec.yaml 删依赖:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  # 移除这行(迁移完成后)
  # tdesign_flutter: ^0.2.7
sh 复制代码
flutter pub get
flutter clean && flutter build apk   # 完整重建一次,确认无编译残留

删之前,一定要把"零残留"确认干净。我有教训:

确认"零残留"要用 grep整个源码 ,而不只看"还有没有 import"。有些地方 import 删了,但注释里、字符串里、甚至某个 // TODO: 改成 TDPicker 里还留着旧名字。这些不影响编译,但会误导后面接手的人。

sh 复制代码
# 扫源码,包括注释和字符串
grep -rn "tdesign\|TDesign\|TD[A-Z]" lib/

# 别忘了 pubspec.lock 和各平台目录也扫一眼
grep -rn "tdesign" pubspec.lock ios/ android/

还有个容易忘的:删依赖后一定要完整重建,而不是热重载。 热重载不会重新解析依赖,改完看着正常,等 CI 一跑才发现某个文件还在引用已删的包。我就这么被 CI 打过一次脸。

那我当初到底该不该引这个库?

各位看官可能问:是不是一开始就不该用第三方 UI 库?

不能这么说。事后诸葛亮谁都会,但当时决策在信息条件下合理------项目要快速出原型,现成组件确实省时间。

我现在判断标准大概这样:

  • 短周期 / 原型验证:用三方库,快就是一切,反正不长期维护。
  • 长期维护项目:如果库版本号还在 0.x,社区活跃度一般,要谨慎。0.x 意味着作者保留随时改 API 的权利,这是人家明说的。
  • 设计规范强的项目:三方库样式定制能力是关键。没暴露足够样式钩子,迟早撞墙。

至于"要不要自己造轮子",我的看法:别造完整 UI 库,但可以造一层薄薄的封装。 像后面 B04 那种基于原生 M3 的公共组件,代码量不大、完全可控,出问题自己就能改。这个投入产出比,我觉得划算。

小结

好啦,这套迁移复盘到这。核心几条:

  1. 迁移 = 先有替代品,再替换,别裸删。删了再想写法,等于把设计决策塞进体力活,必乱。
  2. 动手前先 grep 摸底 + 产出组件映射总表,把决策前置,替换阶段才能机械化推进。
  3. 渐进四批次,按风险排序,每批可验证、可回滚,避免"大爆炸式重构"。
  4. 高频组件放靠后批次。影响面越大,越要等替代品稳了再动。
  5. 移除依赖是最后一步,grep 扫全量源码确认零残留,完整重建验证。
  6. 三方库不是不能用,但长期项目要看版本号和定制能力,0.x 版本心里有数。

回头看,这次迁移最大收获不是"用上了 M3",而是把 UI 控制权拿回了自己手里。以前样式问题只能提 issue 等着,现在打开自己的组件文件改两行就完事。这种踏实感,值。

如果这篇对您有点用,希望看官您用发财的小手点个小赞哈!要是您也做过类似的 UI 库迁移,欢迎在评论区分享一下您的批次划分思路,小可在这边谢谢各位看官了哈!


相关阅读

本文由 FungLeo 主导,Deepseek 优化校阅,转发请注明首发地址,谢谢大家!

相关推荐
技术任我行XTing31 分钟前
【DFX系列】Flutter 鸿蒙应用外接纹理介绍及问题定位
flutter·harmonyos
xy34531 小时前
Axure 9.0 中继器创建与设置步骤
前端·ui·html·axure·原型·产品设计
恋猫de小郭2 小时前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter
大蓝头13 小时前
安装包UI美化之路-借助AI快速使用nsNiuniuSkin制作安装包
ui·安装包·nsis·安装包美化·nsniuniuskin
兰亭妙微UI设计公司18 小时前
兰亭妙微APP界面设计公司分享: iPhone Duo 登场|3 大核心要点,拆解折叠屏 UI 适配设计思路
ui·交互
智购科技自动售货机工厂21 小时前
2026自动售货机端侧AI降本逻辑:从云端API到本地推理的成本重构~YH
人工智能·python·ui·面试·交互
●VON1 天前
Flutter 鸿蒙插件适配实战:用 flutter_native_timezone_2025 1.0.1 读取当前时区与系统目录
flutter·华为·harmonyos·鸿蒙
黑科技iOS上架1 天前
iOS深度混淆flutter应用的最佳实践
flutter·ios·混淆·审核·深度混淆
恋猫de小郭1 天前
CPF-Flutter 社区提出折叠场景分栏(平行视界) 方案
android·前端·flutter