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 中使用
相关推荐
走在路上的菜鸟1 小时前
Android学Flutter学习笔记 第五节 Android视角认知Flutter(插件plugins)
android·学习·flutter
奋斗的小青年!!2 小时前
Flutter开发OpenHarmony打卡进度环组件:实现与跨平台兼容性实践
flutter·harmonyos·鸿蒙
消失的旧时光-19433 小时前
Flutter 列表 + Riverpod 架构实战 —— 从 setState 到状态驱动列表的工程落地
flutter
消失的旧时光-19433 小时前
GetX 从 0 开始:理解 Flutter 的“对象级响应式系统”
flutter
奋斗的小青年!!3 小时前
Flutter跨平台开发鸿蒙应用:表情选择器组件的深度实践
flutter·harmonyos·鸿蒙
消失的旧时光-19433 小时前
Flutter ListView 全解:从 RecyclerView 到声明式列表
flutter
恋猫de小郭3 小时前
Compose Multiplatform 1.10 Interop views 新特性:Overlay 和 Autosizing
android·flutter·macos·kotlin·github·objective-c·cocoa
世人万千丶3 小时前
鸿蒙跨端框架Flutter学习day 1、变量与基本类型-智能家居监控模型
学习·flutter·ui·智能家居·harmonyos·鸿蒙·鸿蒙系统
小白阿龙3 小时前
flutter 与鸿蒙融合开发实战:构建跨平台应用的新范式
flutter·华为·harmonyos
世人万千丶3 小时前
鸿蒙跨端框架Flutter学习day 1、变量与基本类型-咖啡店点餐逻辑
学习·flutter·ui·交互·鸿蒙·鸿蒙系统