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 中使用
相关推荐
不爱吃糖的程序媛40 分钟前
Flutter 三方库适配鸿蒙教程
flutter·华为·harmonyos
2501_919749034 小时前
鸿蒙 Flutter 实战:video_compress 3.1.4 适配 3.27-ohos 全流程
flutter·华为·harmonyos
h64648564h6 小时前
Flutter 国际化(i18n)全指南:一键切换中/英/日多语言
前端·javascript·flutter
kTR2hD1qb11 小时前
Flutter 复杂拖拽排序实战:同源排序 + 跨容器拖拽完整落地
flutter
jingling55512 小时前
Flutter | Dio网络请求实战
android·开发语言·前端·flutter
stringwu15 小时前
Flutter 复杂拖拽排序实战:同源排序 + 跨容器拖拽完整落地
flutter
UnicornDev16 小时前
【Flutter x HarmonyOS 6】设置页面的UI设计
flutter·ui·华为·harmonyos·鸿蒙
G_dou_16 小时前
Flutter+OpenHarmony实战:XMB Tracke
flutter·harmonyos·鸿蒙
●VON1 天前
鸿蒙Flutter实战:分类管理页BottomSheet CRUD
数据库·flutter·华为·harmonyos·鸿蒙
woodWu1 天前
Flutter 复杂拖拽排序实战:同源排序 + 跨容器拖拽完整落地
flutter