保持 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 应有的清晰边界。

相关推荐
初遇你时动了情1 天前
uniapp/flutter中实现苹果IOS 26 毛玻璃效果、跟随滑动放大动画
flutter·ios·uni-app
listhi5201 天前
Vue.js 3的组合式API
android·vue.js·flutter
起风了___1 天前
Flutter 多端音频控制台:基于 audio_service 实现 iOS、Android 锁屏与通知中心播放控制
前端·flutter
leinchu1 天前
Flutter + Codebuddy的坑
flutter
安卓开发者1 天前
第4讲:理解Flutter的灵魂 - “Everything is a Widget”
开发语言·javascript·flutter
起风了___1 天前
Flutter 全局音频播放单例实现(附完整源码)——基于 just_audio 的零依赖方案
前端·flutter
DreamMachine1 天前
Flutter 开发的极简风格音乐播放器
前端·flutter
星释2 天前
鸿蒙Flutter三方库适配指南:08.联合插件开发
flutter·华为·harmonyos
星释2 天前
鸿蒙Flutter三方库适配指南:06.插件适配原理
flutter·华为·harmonyos