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

Flutter Bloc子类型状态创建与使用:继承基类时如何保留指定字段

Flutter Bloc状态子类如何保留部分基类字段并修改指定字段?

首先先修正基类的一个关键问题:你的TimerState继承Equatable时,props只包含了duration,但基类有三个字段,这会导致状态对比时忽略message和isStop,容易引发Bloc状态更新异常。必须把所有参与状态判断的字段都加入props:

abstract class TimerState extends Equatable {
  final int duration;
  final String message;
  final bool isStop;

  const TimerState({
    this.duration = 10,
    this.message = '',
    this.isStop = false,
  });

  @override
  List<Object> get props => [duration, message, isStop]; // 包含所有字段
}

接下来分两种场景实现子类的字段控制:

1. 子类灵活传递所有字段(保留逻辑在Bloc事件中实现)

让每个子类直接继承父类的构造参数,在emit新状态时,基于当前状态的字段值保留需要不变的部分:

class InitialTimerState extends TimerState {
  const InitialTimerState({
    super.duration,
    super.message,
    super.isStop,
  });
}

class TimerStartState extends TimerState {
  const TimerStartState({
    super.duration,
    super.message,
    super.isStop,
  });
}

class TimerStopState extends TimerState {
  const TimerStopState({
    super.duration,
    super.message,
    super.isStop,
  });
}

对应的Bloc事件处理代码:

on<InitialTimer>((event, emit) {
  final current = state;
  emit(InitialTimerState(
    duration: 10, // 设置新的初始时长
    message: '计时器已初始化', // 设置新消息
    isStop: current.isStop, // 保留当前的isStop状态
  ));
});

on<TimerStart>((event, emit) {
  final current = state;
  emit(TimerStartState(
    duration: current.duration, // 保留当前时长
    message: '计时器已启动', // 设置新消息
    isStop: false, // 强制设置为非停止状态
  ));
});

on<TimerStop>((event, emit) {
  final current = state;
  emit(TimerStopState(
    duration: current.duration, // 保留当前时长
    message: '计时器已停止', // 设置新消息
    isStop: true, // 强制设置为停止状态
  ));
});

2. 子类固定部分字段值(简化Bloc调用)

如果某些字段在子类中有固定值(比如TimerStartState的isStop永远是false),可以在子类构造中直接锁定这些字段:

class InitialTimerState extends TimerState {
  const InitialTimerState({
    super.duration = 10,
    super.message = '计时器初始化',
    super.isStop, // 允许保留外部传入的isStop
  });
}

class TimerStartState extends TimerState {
  const TimerStartState({
    super.duration,
    super.message = '计时器启动',
  }) : super(isStop: false); // 固定isStop为false,无需外部传递
}

class TimerStopState extends TimerState {
  const TimerStopState({
    super.duration,
    super.message = '计时器停止',
  }) : super(isStop: true); // 固定isStop为true
}

对应的Bloc事件处理可以简化:

on<InitialTimer>((event, emit) {
  final current = state;
  emit(InitialTimerState(isStop: current.isStop));
});

on<TimerStart>((event, emit) {
  final current = state;
  emit(TimerStartState(duration: current.duration));
});

on<TimerStop>((event, emit) {
  final current = state;
  emit(TimerStopState(duration: current.duration));
});

补充:优化BlocConsumer监听逻辑

你的listenWhen条件是current.message != previous.message,如果需要在状态类型切换时也触发监听(比如从InitialTimerState切到TimerStartState),可以修改逻辑:

listenWhen: (previous, current) {
  // 要么message变化,要么状态类型不同
  return current.message != previous.message || current.runtimeType != previous.runtimeType;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:07:42