外包三年跳甲方后,我用Flutter重构了第一个跨端项目

云计算Cloud
2026-08-13 23:06
阅读 399

一个让我破防的性能问题

六月中旬,组里接了个内部工具链需求,要同时覆盖Android、iOS和Web端。技术选型会上我提了Flutter,被老同事当场怼:“渲染性能不行,复杂列表掉帧掉到你怀疑人生。”

我没接话。外包三年做过两个Flutter项目,我知道问题不在框架,在于用的人。很多人拿写Java的思路硬套,一个setState刷新整个页面,列表不用ListView.builder,图片不缓存,动画不用AnimatedBuilder,然后甩锅给框架。就像开手动挡全程二档踩到六千转,然后说发动机不行。

从零开始的第一行代码

我决定把之前用原生写的报销审批App用Flutter重构一遍,验证一件事:从第一行代码就按性能优化思路来写,Flutter能做到什么程度。

项目结构直接按feature分模块:

lib/
  features/
    expense/
      data/
      domain/
      presentation/
    approval/
    report/
  core/
    network/
    storage/
    widgets/

这个结构对性能没有直接影响,但它逼着你在写代码前想清楚数据流向。性能优化的本质,就是减少不必要的工作量。

三个让我印象深刻的性能坑

第一个坑:列表。 报销列表页每页20条数据。一开始图省事用ListViewColumn,数据一多帧率掉到40以下。改成ListView.builder配合itemExtent固定高度,加上RepaintBoundary隔离重绘区域,帧率稳定在58-60。itemExtent告诉Flutter每个item高度固定,列表计算可视区域时无需测量每个子组件,性能提升非常可观。列表项高度一致的话,一定要用

第二个坑:状态管理。 审批详情页有复杂表单,十几个输入框加联动逻辑。一开始用setState,每敲一个字符整个页面rebuild,键盘弹出时卡顿明显。改成RiverpodStateNotifier配合Consumer做局部刷新,输入流畅度直接拉满。那段时间我靠这些优化,把原本要通宵的活压缩到了晚上十点前。

第三个坑:图片。 报销单上传发票照片,原图动辄5-8MB,不处理直接显示,列表页直接OOM。用cached_network_image做缓存,配合ResizeImage在内存中降采样,缩略图控制在200KB以内,加载从肉眼可见的延迟变成秒开。

一道让我冒冷汗的问题

七月底组里来了个实习生,有天吃饭问我:“Flutter的BuildContext在异步操作之后使用会有什么问题?”

这不是经典的mounted检查问题吗?但更深的点是:BuildContext的生命周期和Element绑定,Widget是不可变的配置,真正持有状态的是Element。异步回调回来时,如果对应的Element已被卸载,直接用context就会触发defunct element错误。

他追问:“那LangGraph这种有状态图执行框架,和Flutter的状态管理有什么共通之处?”

这个问题有点超纲。LangGraph是LLM Agent编排框架,核心是用图结构管理状态流转和节点执行。但它的设计思路和Flutter的InheritedWidget有异曲同工之处:状态变更沿图的边传播,只有依赖该状态的节点才会重新执行。 这不就是依赖注入和局部刷新的思想吗?

我跟他聊了二十分钟。外包三年,什么乱七八糟的问题都见过,这些积累在甲方反而成了差异化优势。

重构结果和一些真心话

八月初重构版上线内部测试,对比原生旧版本:

  • 冷启动:从2.8秒降到1.4秒
  • 列表滑动帧率:稳定59-60fps
  • 包体积:从87MB降到41MB
  • 崩溃率:从0.8%降到0.15%

当初怼我的老同事没再说什么。但我想说的不是Flutter有多好,而是:框架只是工具,性能的上限取决于写代码的人对底层机制的理解深度。

回看三年外包,工资从15k涨到跳槽后的22k,涨幅不算大。但那些一个人扛项目、半夜被客户电话叫醒改bug的日子,逼着我养成了一个习惯:每写一行代码,都问自己一句“这行代码在运行时到底做了什么”。

这个习惯,比任何框架、任何语言都值钱。

不管你在外包还是甲方,不管写Flutter还是Java,真正的成长不是学会了多少个框架,而是开始关心每一帧渲染、每一次内存分配、每一个异步回调背后的代价。那才是从“码农”到“工程师”的分水岭。

评论 0

最热最新
暂无评论
云计算CloudLv.1
0
影响力
0
文章
0
粉丝