如何用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
相关产品推荐
相关产品推荐

