flutter 确实不需要 hooks

之前写过一篇文章:juejin.cn/post/756852...

最近有人在评论区指责我不懂 hooks、不懂 signals、不懂前端潮流。那篇文章中,我对 hooks 还保留了一些余地,认为某些场景下可能确实有其必要性。但直到我深入研究了 flutter_hooks 这个库的起源,我的想法发生了改变。

事情的起因是,该库作者在 github.com/flutter/flu... 中提出状态复用困难的问题,希望借鉴 React 的 hooks 模式来解决。但 Flutter 官方维护者并不认同 hooks 与状态复用之间存在必然联系,因此不打算提供官方支持。

尽管如此,作者在这几年里始终坚持自己的观点,创建了 flutter_hooks 库,将 React 的那套 API 完整地移植到了 Flutter 中。

我个人也反对将 hooks 引入 Flutter。如果问题是状态复用困难,难道 hooks 就是唯一的解决方案吗?显然不是。

我们完全可以借鉴 Android 的 LifecycleObserver 模式,将逻辑抽离出来实现最大化复用,达到与 hooks 相同甚至更好的效果。本质上,hooks 也是对生命周期的一种封装,只是它在封装生命周期之外还附加了许多额外功能。但这些额外功能与状态复用的核心问题关系不大,我认为这更像是为了使用 hooks 而强行引入 hooks。

具体实现代码 :github.com/lwj1994/sta...

使用文档

Flutter State Observer

使用 Observer 模式解决状态复用问题的 Flutter 包。

特性

  • LifecycleObserver: 用于创建可复用状态观察者的基类。
  • LifecycleObserverMixin : 用于在 State 中管理观察者生命周期的 mixin。
  • 常用观察者 :
    • AnimControllerObserver: 可复用的 AnimationController 逻辑。
    • ScrollControllerObserver: 管理 ScrollController
    • TabControllerObserver: 管理 TabController
    • TextEditingControllerObserver: 管理 TextEditingController

用法

自定义观察者

你可以通过继承 LifecycleObserver 轻松创建自己的观察者。

示例:一个 UserDataObserver,它能够:

  1. onInit 中初始化数据获取。
  2. onUpdate 中当 userId 变化时重新获取数据。
  3. onBuild 中记录调试信息。
dart 复制代码
import 'package:flutter/material.dart';
import 'package:state_lifecycle_observer/state_lifecycle_observer.dart';

class Data {
  final String id;
  final String info;
  Data(this.id, this.info);
}

class UserDataObserver extends LifecycleObserver<ValueNotifier<Data?>> {
  // 获取 Widget 最新参数的机制
  final String Function() getUserId;
  
  // 用于追踪变化的内部状态
  late String _currentUserId;

  UserDataObserver(
    super.state, {
    required this.getUserId,
  });

  @override
  void onInit() {
    target = ValueNotifier(null);
    _currentUserId = getUserId();
    _fetchData(_currentUserId);
  }

  @override
  void onUpdate() {
    // 检查依赖 (userId) 是否发生变化
    final newUserId = getUserId();
    if (newUserId != _currentUserId) {
      debugPrint('UserId changed from $_currentUserId to $newUserId');
      _currentUserId = newUserId;
      _fetchData(_currentUserId);
    }
  }

  @override
  void onBuild(BuildContext context) {
    debugPrint('Building with user: $_currentUserId');
  }

  @override
  void onDispose() {
    target.dispose();
  }

  void _fetchData(String id) async {
    // 模拟网络请求
    await Future.delayed(const Duration(milliseconds: 500));
    if (_currentUserId == id) { // 避免竞态条件
      target.value = Data(id, 'Info for $id');
    }
  }
}

与 flutter_hooks 的比较

特性 state_lifecycle_observer flutter_hooks
范式 OOP (类) 函数式 (Hooks)
基类 标准 StatefulWidget HookWidget
生命周期 显式 (onInit, onDispose) 隐式 (useEffect)
学习曲线 低 (标准 Flutter) 中 (Hooks 规则)
黑魔法 低 (Mixin + List) 高 (Element 逻辑)
条件逻辑 随处支持 不允许在 build 中使用
相关推荐
音浪豆豆_Rachel3 小时前
Flutter鸿蒙化之深入解析Pigeon可空返回与参数设计:nullable_returns.dart全解
flutter·harmonyos
音浪豆豆_Rachel4 小时前
Flutter鸿蒙跨平台测试策略解析:从基础Widget测试到平台集成验证
flutter·harmonyos
音浪豆豆_Rachel4 小时前
Flutter鸿蒙跨平台通信协议解析:Pigeon生成的Dart端桥接艺术
flutter·华为·harmonyos
子榆.4 小时前
Flutter 与开源鸿蒙(OpenHarmony)分布式能力实战:基于软总线实现跨设备协同
flutter·开源·harmonyos
光影少年5 小时前
前端开发桌面应用开发,Flutter 与 Electron如何选?
javascript·flutter·electron
音浪豆豆_Rachel5 小时前
Flutter鸿蒙文件选择器平台适配层:标准化接口与平台实现的桥梁
flutter·harmonyos
星海浮沉5 小时前
一文了解 Flutter 动画
flutter·动画
音浪豆豆_Rachel5 小时前
Flutter鸿蒙化之深入解析Pigeon基本数据类型:primitive.dart全解
flutter·华为·harmonyos