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

Flutter Bloc二次点击提交按钮无法触发加载弹窗问题

问题根因
  • Bloc默认基于Equatable的props判断状态是否相同,你的Loading状态props返回空数组,前后两次Loading状态会被判定为完全相同,不会触发BlocListener的回调
  • 用户手动关闭加载弹窗时,仅关闭了弹窗路由,没有同步更新Bloc的状态,Bloc当前状态会一直停留在Loading,第二次提交时再次yield的Loading会被去重,不会触发弹窗显示
  • 额外隐患:Login事件重写的props返回空数组,会导致相同参数的重复提交事件被Bloc直接忽略
修复方案
  1. 修正事件类的props定义
class Login extends SignInEvent{
  @override
  List<Object?> get props => [userName, password, pin]; // 修正props返回值

  final String userName;
  final String password;
  final String pin;

  Login(this.userName,this.password,this.pin) : super([userName,password,pin]);
}
  1. 新增重置状态的事件,处理用户手动关闭弹窗的场景
    首先在事件类新增重置事件:
class ResetSignInState extends SignInEvent {
  @override
  List<Object?> get props => [];
}

在Bloc逻辑中添加重置事件的处理逻辑:

if (event is ResetSignInState) {
  yield SignInInitial();
}
  1. 给加载弹窗添加关闭回调,关闭时同步重置Bloc状态
    如果你的弹窗工具类支持关闭回调,直接修改UI层BlocListener中的弹窗调用逻辑:
if(state is Loading){
  loading.showAlertDialog(
    context,
    // 手动关闭弹窗时触发,重置Bloc状态到初始值
    onDismiss: () => context.read<SignInBloc>().add(ResetSignInState()),
  );
}

如果弹窗工具类没有内置关闭回调,可以通过showDialog的then回调监听关闭事件:

showDialog(
  context: context,
  builder: (context) => const LoadingAlert(),
).then((_) {
  // 弹窗关闭时触发
  context.read<SignInBloc>().add(ResetSignInState());
});
  1. 优化Bloc请求逻辑,避免异步操作返回后状态异常
if (event is Login) {
  // 先切回初始状态,保证Loading状态变更能被监听到
  yield SignInInitial();
  yield Loading();
  final login = await loginUser(event.userName, event.password, event.pin);
  // 仅当当前仍为Loading状态时返回结果,避免用户已取消后还触发后续逻辑
  if (state is Loading) {
    yield Loaded(login);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 04:00:01