You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Riverpod 2实现多个TruZapBtn实例的独立状态管理?

解决Riverpod 2中多按钮独立状态的问题

你的核心问题是当前的TruZapBtnBLC是全局单例Provider,所有按钮共享同一状态,导致点击一个按钮所有按钮都变化。要实现独立状态,需要使用Riverpod Family Provider,它允许你根据传入的参数(比如按钮的唯一Key)创建独立的状态实例。

步骤1:改造State Provider为Family类型

将TruZapBtnBLC改为family provider,接收Key作为参数,每个Key对应一个独立的状态实例:

@riverpod
class TruZapBtnBLC extends _$TruZapBtnBLC {
  // 接收按钮的唯一Key作为family参数
  @override
  TruZapBtnMDL build(Key buttonKey) {
    return TruZapBtnMDL(
      isEnabled: true,
      isPressed: false,
      isLockDown: false,
      isInitBuild: true,
      key: buttonKey, // 使用传入的Key作为模型的key
      colorLocked: Colors.amber,
      colorPressed: Colors.blueAccent,
    );
  }

  // 添加状态更新方法,封装业务逻辑
  void handleTapDown() {
    state = state.copyWith(isPressed: true);
  }

  void handleTapUp() {
    state = state.copyWith(isPressed: false);
  }

  void toggleLock() {
    state = state.copyWith(isLockDown: !state.isLockDown);
  }
}

步骤2:简化Widget类,移除静态变量

原Widget中的静态_blcTZB会导致状态共享,需要移除,改为通过自身的key获取对应的family provider实例:

class TruZapBtn extends ConsumerWidget {
  // 仅保留必要的配置参数,状态由Provider统一管理
  final Key key;
  final Color colorPressed;
  final Color colorLocked;

  const TruZapBtn({
    required this.key,
    this.colorPressed = Colors.blueAccent,
    this.colorLocked = Colors.amber,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 根据当前按钮的key,监听对应的family provider状态
    final buttonState = ref.watch(truZapBtnBLCProvider(key));
    // 获取对应的notifier,用于触发状态更新
    final buttonNotifier = ref.read(truZapBtnBLCProvider(key).notifier);

    return InkWell(
      onTap: buttonState.isEnabled ? () => buttonNotifier.toggleLock() : null,
      onTapDown: buttonState.isEnabled ? (_) => buttonNotifier.handleTapDown() : null,
      onTapUp: buttonState.isEnabled ? (_) => buttonNotifier.handleTapUp() : null,
      child: Container(
        width: 100,
        height: 50,
        color: buttonState.isLockDown
            ? colorLocked
            : buttonState.isPressed
                ? colorPressed.withOpacity(0.8)
                : colorPressed,
        alignment: Alignment.center,
        child: Text(buttonState.isLockDown ? '锁定' : '未锁定'),
      ),
    );
  }
}

步骤3:保持原实现代码不变

初始化按钮时只需传入唯一Key,每个按钮会自动关联对应的独立状态:

TruZapBtn tzbBtn01 = TruZapBtn(key: const Key('TZB01'));
TruZapBtn tzbBtn02 = TruZapBtn(key: const Key('TZB02'));
TruZapBtn tzbBtn03 = TruZapBtn(key: const Key('TZB03'));

关键改动说明

  • Family Provider:通过truZapBtnBLCProvider(key)为每个不同的Key创建独立的状态实例,彻底解决状态共享问题。
  • 移除静态变量:原Widget中的静态_blcTZB是导致状态混乱的根源,改用ref.watch和ref.read针对当前按钮的Key获取状态和通知器。
  • 状态更新封装:将状态修改逻辑封装在TruZapBtnBLC的方法中,符合Riverpod的状态管理规范,避免直接修改状态。

内容的提问来源于stack exchange,提问作者SilSur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:34:54