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

Flutter Bloc的mapEventToState仅执行一次后续UI无更新问题求解

问题核心原因

Bloc默认会对比前后两次yield的状态,如果是同一个对象实例,就会判定状态无变化,不会触发UI的builder回调。你代码的问题出在两处:

  1. AuthState是可变类,没有实现相等性对比逻辑
  2. 你在mapEventToState中直接修改原state对象的属性,yield的还是旧的状态实例,Bloc识别不到状态变更

修复步骤

1. 改造AuthState为不可变类,支持相等性判断

推荐用Equatable简化代码,首先在pubspec.yaml的dependencies下添加依赖:

equatable: ^2.0.5

然后修改auth_state.dart:

import 'package:equatable/equatable.dart';

class AuthState extends Equatable {
  final bool isLoggedIn;

  const AuthState({this.isLoggedIn = false});

  @override
  List<Object?> get props => [isLoggedIn];
}

如果不想引入Equatable,也可以自己重写==和hashCode:

class AuthState {
  final bool isLoggedIn;

  AuthState({this.isLoggedIn = false});

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is AuthState &&
          runtimeType == other.runtimeType &&
          isLoggedIn == other.isLoggedIn;

  @override
  int get hashCode => isLoggedIn.hashCode;
}

2. 修改AuthBloc逻辑,每次yield新的状态实例

不要修改原state对象,每次都创建新的AuthState实例返回:

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  AuthBloc() : super(const AuthState());

  @override
  Stream<AuthState> mapEventToState(AuthEvent event) async* {
    switch (event.eventType) {
      case EventType.login:
        yield AuthState(isLoggedIn: true);
        break;
      case EventType.logout:
        yield AuthState(isLoggedIn: false);
        break;
      default:
        throw Exception('Event not found $event');
    }
  }
}

其余页面代码无需修改,调整后Bloc就能正确识别状态变更,触发UI刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 18:15:01