欢迎光临
我们一直在努力

Flutter 为什么走上了和前端一样的“百家争鸣”?

在这里插入图片描述 在这里插入图片描述

子玥酱
(掘金 / 知乎 / CSDN / 简书 同名)

大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。

我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案, 在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。

技术方向:前端 / 跨端 / 小程序 / 移动端工程化 内容平台:掘金、知乎、CSDN、简书 创作特点:实战导向、源码拆解、少空谈多落地 文章状态:长期稳定更新,大量原创输出

我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。

子玥酱 · 前端成长记录官 ✨ 👋 如果你正在做前端,或准备长期走前端这条路 📚 关注我,第一时间获取前端行业趋势与实践总结 🎁 可领取 11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构) 💡 一起把技术学“明白”,也用“到位”

持续写作,持续进阶。 愿我们都能在代码和生活里,走得更稳一点 🌱

文章目录

    • Flutter 和前端,为什么会一起“状态爆炸”
    • Provider / Riverpod / Bloc,本质上在解决什么问题
      • Provider 的选择
      • Riverpod、Bloc 为什么会出现
    • RN 项目后期的 Redux 地狱,其实不是 Redux 的错
    • Flutter 与前端状态模型的“同构性”
    • 那为什么 iOS 反而看起来更稳定?
      • iOS 的几个天然约束
    • iOS 状态简单的“代价”
    • 一个真正通用的状态分层方法论
      • UI State(页面私有)
      • Domain State(业务状态)
      • App State(全局状态)
    • Flutter Demo:正确拆分状态的方式
      • 业务状态(Domain State)
      • UI 层只关心展示
      • 这里做对了三件事
    • 总结

如果你写 Flutter 写到后期,大概率会有一种熟悉又不安的感觉:

“这个项目怎么越来越像前端了?”

State 到处飞、Provider 套 Provider、Riverpod 和 Bloc 各执一词, 社区天天在争:“谁才是 Flutter 最佳状态管理方案?”

而如果你做过前端,甚至 RN,你会发现—— 这条路,其实我们已经走过一次了。

Flutter 和前端,为什么会一起“状态爆炸”

先说一个很现实的场景。

一个 Flutter 页面最开始可能只是:

  • 一个列表
  • 一个 loading
  • 一个点击事件

bool loading = false;
List<Item> items = [];

一切都很简单。

但很快你会遇到:

  • 下拉刷新
  • 上拉分页
  • 局部 loading
  • 表单校验
  • 异步请求状态
  • 页面间数据共享

于是状态开始分裂:

页面状态
├─ UI 状态(loading / error / empty)
├─ 业务状态(数据、筛选条件)
├─ 交互状态(是否选中、是否展开)
├─ 全局状态(用户、主题、权限)

这一步,Flutter 和前端几乎完全一致。

原因很简单:

Flutter 本质上是一个声明式 UI 框架,而声明式 UI 一定依赖状态驱动。

React、Vue、Flutter 都遵循同一件事:

UI = f(State)

状态一多,管理方式必然分歧, 于是就出现了——百家争鸣。

Provider / Riverpod / Bloc,本质上在解决什么问题

很多人把注意力放在“API 好不好用”上,其实忽略了核心。

这些方案本质都在回答三个问题:

  • 状态放在哪里
  • 谁可以修改状态
  • UI 如何感知变化
  • Provider 的选择

    Provider 的思路很直接:

    • 状态是对象
    • 通过 InheritedWidget 向下传递
    • notifyListeners 触发 rebuild

    class CounterModel extends ChangeNotifier {
    int count = 0;

    void increment() {
    count++;
    notifyListeners();
    }
    }

    ChangeNotifierProvider(
    create: (_) => CounterModel(),
    child: CounterPage(),
    );

    好处很明显:

    • 简单
    • 上手快
    • 适合中小项目

    但问题也很熟悉:

    • 状态和 UI 容易耦合
    • notifyListeners 粒度太粗
    • 大项目后期 rebuild 不可控

    Riverpod、Bloc 为什么会出现

    当项目复杂后,大家开始追求:

    • 更强的约束
    • 更明确的数据流
    • 更少的隐式依赖

    于是:

    • Riverpod 把依赖关系显式化
    • Bloc 强制事件 → 状态的单向流动
    • Redux 更是走到极端:一切都不可变

    这条演化路径,和前端一模一样。

    RN 项目后期的 Redux 地狱,其实不是 Redux 的错

    很多人吐槽:

    “Redux 太复杂了”

    但真正的问题往往是:

    • 所有状态都进了 global store
    • 页面级状态也被当成全局状态
    • reducer 变成上帝文件

    Redux Store
    ├─ user
    ├─ theme
    ├─ homePage
    ├─ detailPage
    ├─ modal
    ├─ tempFlags

    结果就是:

    • 改一个字段,半个项目受影响
    • Action 命名越来越抽象
    • 调试成本指数级上升

    Flutter 项目里如果:

    • 所有状态都塞进 Riverpod global provider
    • 或 Bloc 被当成“万能状态容器”

    结局是一样的。

    Flutter 与前端状态模型的“同构性”

    把技术名词全拿掉,其实两边模型几乎完全重合:

    维度前端Flutter
    UI 更新 Virtual DOM Diff Widget rebuild
    状态来源 props / state constructor / provider
    全局状态 Redux / Zustand Provider / Riverpod
    局部状态 useState StatefulWidget

    差别只在表现形式,不在问题本质。

    所以 Flutter 社区出现多种状态方案,并不是“乱”, 而是必然演化结果。

    那为什么 iOS 反而看起来更稳定?

    再看 iOS。

    MVC、MVVM,看起来好像没那么多争论。

    原因不是 iOS 更先进,而是——限制更多。

    iOS 的几个天然约束

  • UIKit 是命令式
  • ViewController 生命周期强约束
  • View 默认不自动响应状态变化
  • 数据必须手动驱动 UI
  • func updateUI() {
    label.text = viewModel.title
    }

    你不调用,它就不变。

    这其实强行压制了状态规模。

    iOS 状态简单的“代价”

    这种稳定是有代价的:

    • UI 更新需要手动维护
    • 容易出现状态不同步
    • 大量胶水代码
    • 重构成本高

    所以 SwiftUI 出现后, iOS 也开始重新面对 Flutter / React 遇到的问题。

    状态复杂化,不是 Flutter 的问题,而是声明式 UI 的代价。

    一个真正通用的状态分层方法论

    不管 Flutter、前端还是 iOS,本质都可以用同一套分层思路。

    UI State(页面私有)

    • loading
    • tab index
    • 是否展开

    特点:

    • 生命周期 = 页面
    • 不跨页面共享

    用 StatefulWidget / 局部 State 就够了。

    Domain State(业务状态)

    • 列表数据
    • 表单内容
    • 筛选条件

    特点:

    • 页面核心数据
    • 可测试
    • 与 UI 解耦

    用 Provider / Riverpod / Bloc。

    App State(全局状态)

    • 登录用户
    • 权限
    • 主题

    特点:

    • 生命周期 = App
    • 变化频率低

    严格限制数量,能少就少。

    Flutter Demo:正确拆分状态的方式

    业务状态(Domain State)

    class TodoListModel extends ChangeNotifier {
    final List<String> todos = [];

    void addTodo(String text) {
    todos.add(text);
    notifyListeners();
    }
    }

    UI 层只关心展示

    class TodoPage extends StatefulWidget {

    State<TodoPage> createState() => _TodoPageState();
    }

    class _TodoPageState extends State<TodoPage> {
    bool showInput = false;


    Widget build(BuildContext context) {
    final model = context.watch<TodoListModel>();

    return Column(
    children: [
    if (showInput)
    TextField(
    onSubmitted: (text) {
    model.addTodo(text);
    setState(() => showInput = false);
    },
    ),
    Expanded(
    child: ListView(
    children: model.todos
    .map((e) => ListTile(title: Text(e)))
    .toList(),
    ),
    ),
    FloatingActionButton(
    onPressed: () {
    setState(() => showInput = true);
    },
    )
    ],
    );
    }
    }

    这里做对了三件事

  • UI 状态不进 Provider
  • 业务状态不关心 UI
  • rebuild 范围可控
  • 总结

    Flutter 走上“百家争鸣”,不是因为它乱, 而是因为它走在了一条所有声明式 UI 都必须面对的路上。

    前端走过一次 RN 跌过一次 Flutter 正在经历 SwiftUI 也正在路上

    真正重要的不是:

    “你用的是 Provider 还是 Bloc?”

    而是:

    “你有没有想清楚,哪些状态该存在,哪些不该存在。”

    赞(0)
    未经允许不得转载:171主机测评 » Flutter 为什么走上了和前端一样的“百家争鸣”?
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址