Flutter Bloc点击登录按钮不触发Event也不emit状态问题求解
问题修复方案
你代码存在4处核心问题,按优先级修复如下:
1. Login事件类参数接收逻辑错误
你当前的Login事件成员变量被写死为空字符串,构造函数传入的参数完全没有被赋值给实例,修改login_event.dart代码:
class Login extends LoginEvent { // 移除固定赋值,改为仅声明 final String email; final String password; // 构造函数直接绑定实例变量,补全参数类型 const Login(this.email, this.password); @override List<Object?> get props => [ email, password ]; }
2. Bloc异步回调写法错误,逻辑永远不执行
你在then、onError后错误使用=> () {}语法,该写法会返回一个匿名函数但不会执行,内部的逻辑完全不会触发,推荐改用更易维护的async/await写法修改LoginBloc代码:
class LoginBloc extends Bloc<LoginEvent, LoginState> { LoginBloc() : super(LoginState.initial()) { // 补全async标识 on<LoginEvent>((event, emit) async { if (event is Login) { // 可选:先触发加载状态,页面可以做加载动画 emit(LoginState(event.email, event.password, true, ApiError())); try { final response = await ApiService.post(ApiEndpoints.login, { 'email': event.email, 'password': event.password }); if (response.statusCode == 200) { var responseJson = jsonDecode(response.body); MeData meData = MeData.fromJson(responseJson['data']); // 补充登录成功后的状态emit逻辑,比如跳转主页 } else { ApiError apiError = Utilities.parseApiError(response.body); emit(LoginState(event.email, event.password, false, apiError)); } } catch(error) { var apiError = ApiError(); apiError.setGenericErrorMessage("Something went wrong!"); emit(LoginState(event.email, event.password, false, apiError)); } } }); } }
如果你要保留then的写法,只需移除箭头后面的额外括号即可:
.then((response) { // 原有逻辑 }) .onError((error, stackTrace) { // 原有逻辑 })
3. 页面错误提示未绑定Bloc状态
你当前表单的错误提示用的是页面本地的_apiError变量,Bloc返回的state.error更新后不会同步到UI,修改两个输入框的errorText属性:
// 邮箱输入框 errorText: state.error.getFieldError("email") // 密码输入框 errorText: state.error.getFieldError("password")
4. 可选校验项
如果修改完以上三点仍无响应,可在on<LoginEvent>回调的第一行加入打印日志,确认事件是否正常分发到Bloc:
on<LoginEvent>((event, emit) async { print('收到事件:$event'); // 有打印说明事件分发正常,无打印说明上下文找不到LoginBloc // 原有逻辑 }
你当前BlocProvider放在顶层MyApp下,只要LoginPage在MaterialApp的路由栈内,上下文就能正常获取LoginBloc实例。
内容的提问来源于stack exchange,提问作者Wai Yan Hein
相关产品推荐
相关产品推荐

