保持 Widget.build 内部的纯净

保持 Widget.build 内部的纯净

Provider 家族的隐式依赖

使用 Provider 时,开发者常在 build 方法中直接调用 Provider.of 或 watch :

dart 复制代码
  
Widget build(BuildContext context) {
  final user = Provider.of<User>(context); // 状态逻辑直接嵌入 UI
  final theme = context.watch<ThemeProvider>();
  return Text(user.name, style: TextStyle(color: theme.textColor));
}

这里的 build 方法不仅要描述 UI,还要处理状态订阅,一旦更换状态管理方式,所有 Provider.of 调用都需逐个修改,耦合度极高。

Bloc 的层级嵌套

Bloc 虽强调事件流分离,但在 UI 层仍需通过 BlocBuilder 嵌入状态逻辑:

dart 复制代码
  
Widget build(BuildContext context) {
  return BlocBuilder<CounterBloc, int>(
    builder: (context, state) { // 状态处理逻辑混杂在 UI 构建中
      return Text('$state');
    },
  );
}

BlocBuilder 作为 UI 组件的一部分,让状态管理的实现细节暴露在 build 方法里,组件无法脱离 Bloc 框架独立复用。

Riverpod 的即时订阅

Riverpod 的 ref.watch 虽简化了订阅,但仍需在 build 中显式声明依赖:

dart 复制代码
  
Widget build(BuildContext context, WidgetRef ref) {
  final counter = ref.watch(counterProvider); // 状态订阅与 UI 强绑定
  return Text('$counter');
}

build 方法被迫知晓 counterProvider 的存在,一旦 provider 定义变更,所有 build 的引用处都要调整,违背了"UI 只关心数据,不关心数据来源"的原则。

为什么不应该在 build 中耦合状态管理?

  • 破坏单一职责: build 方法的核心是描述 UI 结构,混入状态订阅后,既要处理渲染逻辑,又要管理状态依赖,导致代码混乱。

  • 阻碍组件复用:耦合了特定状态管理逻辑的 UI 组件,无法在其他框架或场景中直接复用,降低了代码的灵活性。

  • 增加维护成本:当状态管理方案更换时,所有 build 方法中的订阅代码都需重构,牵一发而动全身。

替代方案

我在使用上述流行库后,发现他们的设计弊端,于是自己重新编写了一个简洁版的状态管理,没错状态管理就是一个很简单的东西,就像 Android 的 ViewModel 一样。本质上就是一个跟随生命周期的 vm 实例管理。但是不理解 flutter 这边的开发整的如此花里胡哨。

一种推荐:用 pub.dev/packages/vi... 解耦状态与 UI。

build 方法仅通过简单属性获取数据,彻底剥离状态管理细节:

dart 复制代码
// ViewModel 层封装状态逻辑
class UserViewModel extends ViewModel{
  final User user = User(name: 'Alice');
  // 状态更新逻辑完全封装在此
}


class UserPageState extends State<UserPage> with ViewModelStateMixin{
  late final UserViewModel _viewModel;
  void initState(){
    _viewModel = watchViewModel<UserViewModel>(factory: DefaultViewModelFactory(build:UserViewModel.new));
  }


  /// UI 层仅关注展示. 只持有 _viewModel。后续如何想替换底层的状态管理,
  /// 修改 _viewModel 的实现即可。
  Widget build(BuildContext context) {
    return Text(_viewModel.user.name); // 无任何状态订阅代码
  }
}

总结

让 UI 组件回归纯粹的展示职责,状态管理逻辑集中在 ViewModel ,不仅提升了代码可读性,还让组件复用和框架迁移变得轻松。当需要更换状态管理方式时,只需修改 ViewModel 内部实现, build 方法无需变动------这才是状态与 UI 应有的清晰边界。

相关推荐
程序员Ctrl喵13 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难14 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡15 小时前
flutter列表中实现置顶动画
flutter
始持16 小时前
第十二讲 风格与主题统一
前端·flutter
始持16 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持16 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜16 小时前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴17 小时前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区17 小时前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎18 小时前
树形选择器组件封装
前端·flutter