Flutter Bloc实现手机号认证时emit状态失败的问题求助
Flutter Bloc 手机号认证emit失败问题
在Flutter应用中使用Bloc实现手机号认证功能,点击发送验证码按钮触发sendOtpEvent后,verifyOTPState无法正常被emit,出现错误:'emit was called after an event handler completed normally'。已尝试给codeSent回调添加async但无效。
相关代码
- Bloc事件处理代码:
on<sendOtpEvent>((event,emit)async{ await _auth.verifyPhoneNumber( phoneNumber:event.number, verificationCompleted:(PhoneAuthCredential credentials){}, verificationFailed: (FirebaseAuthException e) { emit(ErrorState(error: e.message.toString())); }, codeSent: (String verificationId, int? forceResendingToken) async{ emit(verifyOTPState(verificationID: verificationId)); }, codeAutoRetrievalTimeout: (String verificationId) { }); });
- 错误日志:
E/flutter ( 7268): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:bloc/src/emitter.dart': Failed assertion: line 114 pos 7: '!_isCompleted': E/flutter ( 7268): E/flutter ( 7268): emit was called after an event handler completed normally. E/flutter ( 7268): This is usually due to an unawaited future in an event handler. E/flutter ( 7268): Please make sure to await all asynchronous operations with event handlers E/flutter ( 7268): and use emit.isDone after asynchronous operations before calling emit() to E/flutter ( 7268): ensure the event handler has not completed. E/flutter ( 7268): E/flutter ( 7268): **BAD** E/flutter ( 7268): on<Event>((event, emit) { E/flutter ( 7268): future.whenComplete(() => emit(...)); E/flutter ( 7268): }); E/flutter ( 7268): E/flutter ( 7268): **GOOD** E/flutter ( 7268): on<Event>((event, emit) async { E/flutter ( 7268): await future.whenComplete(() => emit(...)); E/flutter ( 7268): });
解决方案
问题核心是verifyPhoneNumber的await不会等待codeSent等回调执行完毕,事件处理函数在verifyPhoneNumber返回后就已结束,后续codeSent中的emit操作就会触发错误。可以通过Completer手动等待回调完成:
修改后的Bloc事件处理代码:
on<sendOtpEvent>((event, emit) async { final completer = Completer<void>(); await _auth.verifyPhoneNumber( phoneNumber: event.number, verificationCompleted: (PhoneAuthCredential credentials) { completer.complete(); }, verificationFailed: (FirebaseAuthException e) { emit(ErrorState(error: e.message.toString())); completer.complete(); }, codeSent: (String verificationId, int? forceResendingToken) { emit(verifyOTPState(verificationID: verificationId)); completer.complete(); }, codeAutoRetrievalTimeout: (String verificationId) { completer.complete(); }, ); // 等待任意回调执行完成后再结束事件处理 await completer.future; });
额外建议:遵循Dart命名规范,将事件类sendOtpEvent改为SendOtpEvent,状态类也保持大驼峰命名(如VerifyOtpState、ErrorState),提升代码可读性。
内容的提问来源于stack exchange,提问作者Dnyanesh Kulkarni
相关产品推荐
相关产品推荐

