从外包到甲方:一个老广程序员的 Flutter 状态管理实战与思考

TypeScript守夜人
2026-02-15 19:07
阅读 362

去年十月,我还在天河软件园一家外包公司加班到凌晨两点,改着第 8 版需求文档里“微调一下 UI”的按钮颜色。那天广州下了场冷雨,我裹着那件穿了三年的优衣库羽绒服,站在珠江新城地铁站口,看着对面写字楼里还亮着的灯,心里只有一个念头:再这样下去,我怕是要在35岁前被优化掉

那时我月薪15k,房租3500,老婆刚怀上二胎,压力山大。面试投了快两个月,终于在年底收到一家本地电商公司的终面通知——甲方,自研产品,Flutter 全栈开发岗。HR 电话里说:“我们最近在重构 App,状态管理这块有点混乱,你有实战经验吗?”

我嘴上答“有”,心里却慌得一批。因为在外包,我写的 Flutter 项目基本都是 setState 走天下,稍微复杂点就靠 Provider 硬扛,连 Riverpod 都没正经用过。更别提什么 BLoC、MobX、GetX 了——这些词我只在 GPT-4 生成的“Flutter 面试题 Top 20”里见过。


面试现场:被问懵的状态管理题

面试那天是周五下午,地点在越秀区一栋老式写字楼里,空调开得跟冰窖似的。技术负责人是个戴眼镜的中年大哥,上来就问:

“你们之前项目怎么处理状态共享?比如用户登录后,首页、购物车、个人中心都要同步更新。”

我硬着头皮说:“用 Provider,把用户信息放全局,然后 Consumer 监听变化。”

他点点头,又问:“如果某个页面依赖多个状态,比如商品列表要同时响应搜索关键词、分类筛选、网络加载状态,你怎么组织?”

我卡壳了。脑子里闪过一堆 if (loading) ... else if (error) ... else if (data != null) 的代码,但说不出系统性的方案。最后只能老实交代:“我们项目没那么复杂,一般拆成几个小 Provider,或者直接用 FutureBuilder。”

他笑了笑,没为难我,但补充了一句:“其实我们希望团队能统一状态管理规范,避免后期维护像‘意大利面条’。”

回家路上,我越想越焦虑。当晚翻出 GPT-4,让它模拟一场“高级 Flutter 开发面试”,重点问状态管理。结果它甩给我一串问题:

  • Provider 和 Riverpod 本质区别是什么?
  • BLoC 如何避免内存泄漏?
  • 在大型项目中,如何选择合适的状态管理方案?
  • 状态管理与架构设计(如 Clean Architecture)如何结合?

我盯着屏幕,手心冒汗。那一刻我意识到:外包三年,我缺的不是写代码的能力,而是系统性思维和工程规范意识。


入职后的真实战场:从混乱到有序

幸运的是,我还是拿到了 offer,月薪涨到22k。入职第一周,我就被分配到重构商品详情页的任务——这个页面当时用了三种状态管理方式:setState 控制 Tab 切换、Provider 管理购物车数量、FutureBuilder 加载商品数据。代码耦合严重,测试覆盖率几乎为零。

我和组里一个叫阿强的同事(地道潮汕人,但讲粤语比我溜)一起啃这块硬骨头。我们开了个会,决定统一用 Riverpod + AsyncNotifier 作为新标准。为什么选它?

  1. 编译安全:相比 Provider,Riverpod 不依赖 BuildContext,不会因为 widget 树变化导致监听失效。
  2. 组合性强:可以轻松组合多个 provider,比如 ref.watch(userProvider).whenData(...)
  3. 测试友好:每个 notifier 可以独立单元测试,不用启动整个 widget 树。

举个具体例子:商品详情页需要同时获取商品信息、用户收藏状态、促销活动。以前是三个 FutureBuilder 嵌套,现在我们这样写:

final productDetailProvider = AsyncNotifierProvider.autoDispose<
    ProductDetailNotifier, ProductDetail>(
  ProductDetailNotifier.new,
);

class ProductDetailNotifier extends AsyncNotifier<ProductDetail> {
  @override
  Future<ProductDetail> build() async {
    final productId = ref.watch(productIdProvider);
    final user = await ref.watch(userProvider.future);
    
    final product = await repository.fetchProduct(productId);
    final isFavorite = await repository.checkFavorite(user.id, productId);
    final promotions = await repository.getPromotions(productId);
    
    return ProductDetail(
      product: product,
      isFavorite: isFavorite,
      promotions: promotions,
    );
  }
}

在 UI 层,只需一行:

final detail = ref.watch(productDetailProvider);
return detail.when(
  loading: () => LoadingView(),
  error: (err, _) => ErrorView(err),
  data: (data) => DetailView(data),
);

清晰、可测、可维护。 这就是甲方和外包最大的区别——他们愿意花时间做“正确的事”,而不是“快的事”。


我的 Flutter 状态管理最佳实践总结

经过半年实战,我总结出几点心得,分享给还在挣扎的兄弟们:

1. 小项目用 setState + Provider 足够

别一上来就搞 BLoC 或 GetX。如果只是个内部工具或 MVP 产品,过度设计反而拖慢进度。我之前外包项目很多就是这种,硬上架构反而让客户觉得“效率低”。

2. 中大型项目首选 Riverpod

它解决了 Provider 的痛点,又不像 BLoC 那样样板代码多。配合 AsyncNotifier,异步逻辑一目了然。而且社区生态成熟,GPT-4 也能给出靠谱示例(虽然别全信,但至少方向对)。

3. 状态要分层:UI 状态 vs 业务状态

  • UI 状态(比如弹窗是否显示、Tab 选中项):放在 widget 自身或局部 provider。
  • 业务状态(用户信息、订单数据):必须全局管理,且要持久化(配合 shared_preferences 或 Hive)。

4. 面试时别背概念,讲场景

当被问“你怎么选状态管理方案”,别说“BLoC 更好因为响应式”。要说:

“我们上个项目有 20+ 页面共享用户状态,初期用 Provider 导致 rebuild 过多,后来迁移到 Riverpod,通过 select 优化监听粒度,帧率从 52 提升到 58。”

用数据和结果说话,比背八股文强一百倍。


从外包到甲方,我最大的成长不是技术

上周五晚上,我和老婆在西华路吃牛杂,她问我:“最近加班少好多,是不是甲方舒服点?”

我笑着说:“不是舒服,是做事有章法了。以前在外包,天天救火;现在在甲方,我们在造消防系统。”

其实 Flutter 状态管理只是表象,背后是工程思维的升级。外包教会我快速交付,甲方教会我如何构建可持续演进的系统。而 GPT-4 这类工具,不是用来抄答案的,而是帮我们快速验证思路、查漏补缺——就像当年我师傅教我用 Google 一样。

如果你也在外包,想跳甲方,别怕。我月薪15k的时候也觉得自己没戏。但只要你在每个项目里多问一句“有没有更好的方式”,多花一小时研究官方文档,机会总会来。

程序员最怕的不是技术难,而是停止思考。


最后一点真心话

今年三月,我带了一个实习生,也是老广,华工毕业的。他第一天就问我:“哥,状态管理到底该学哪个?网上说法太多了。”

我泡了壶普洱,慢慢说:“没有银弹。但你可以记住三件事:

  1. 先理解问题,再选工具。状态管理的本质是“当数据变,视图自动更新”。
  2. 保持简单。能用 10 行代码解决的,别写 100 行架构。
  3. 写给人看,不是给机器跑。半年后你自己都看不懂的代码,就是垃圾。

他似懂非懂地点头。我想,这大概就是传承吧。

现在的我,依然会在深夜 debug 时骂一句“顶你个肺”,但心里踏实多了。因为我知道,自己写的每一行代码,都在为一个真实的产品服务,而不是某个明天就消失的外包需求。

共勉。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝