使用不包含 PhoneAuthenticationBloc 类型的 Bloc 的上下文调用 BlocProvider.of()。扑
Posted
技术标签:
【中文标题】使用不包含 PhoneAuthenticationBloc 类型的 Bloc 的上下文调用 BlocProvider.of()。扑【英文标题】:BlocProvider.of() called with a context that does not contain a Bloc of type PhoneAuthenticationBloc. Flutter 【发布时间】:2021-02-07 10:17:20 【问题描述】:我在MultiBlocProvider
中创建块,它的子对象是BlocBuilder
,它返回MultiBlocListener
,但在发送事件时
BlocProvider.of<PhoneAuthenticationBloc>(context).add(VerifyPhoneNumberEvent(phoneNumber: controller.text.replaceAll(' ', '')));
我得到BlocProvider.of() called with a context that does not contain a Bloc of type PhoneAuthenticationBloc
,而其他集团工作正常。
你能发现PhoneAuthenticationBloc()
有什么问题吗?
@override
Widget build(BuildContext context)
return MultiBlocProvider(
providers: [
BlocProvider<PhoneAuthenticationBloc>(
create: (context) => PhoneAuthenticationBloc(userRepository: UserRepository()),
),
// BlocProvider<AuthenticationBloc>(
// create: (context) => AuthenticationBloc(userRepository: UserRepository()),
// lazy: false,
// ),
// BlocProvider<UserBloc>(
// create: (context) => UserBloc(),
// lazy: false,
// ),
BlocProvider<BookingBloc>(
create: (context) => BookingBloc(user: widget.user),
),
BlocProvider<OrderBloc>(
create: (context) => OrderBloc(user: widget.user),
),
BlocProvider<PaymentBloc>(
create: (context) => PaymentBloc(user: widget.user),
lazy: false,
),
BlocProvider<CartBloc>(
create: (context) => CartBloc()..add(LoadCart()),
),
],
child: BlocBuilder<PaymentBloc, PaymentState>(
builder: (context, state)
if (state is InitialStatePayment)
return MultiBlocListener(
listeners: [
BlocListener<PhoneAuthenticationBloc, AuthenticationState>(
listener: (BuildContext context, AuthenticationState state)
...
FlatButton.icon(
color: Colors.orange,
onPressed: ()
print('pay pressed');
print(
'bookingStart is $widget.bookingStart, selected shop is $widget.selectedShop');
if (isVerified == true)
...
else
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context)
return SingleChildScrollView(
child: ValidatePhoneDialog(
controller: controller,
onPressed: ()
if (controller.text.length >= 9)
Navigator.pop(context);
showDialog(
context:context,
barrierDismissible: false,
builder: (BuildContext context)
return VerifyingDialog();
);
BlocProvider.of<PhoneAuthenticationBloc>(context).add(VerifyPhoneNumberEvent(phoneNumber: controller.text.replaceAll(' ', '')));
else
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong number'),
style: TextStyle(color: Colors.white))));
),
);
);
,
icon: Icon(
Icons.payment,
color: Colors.white,
),
label: Text(
AppLocalizations.instance.text('Pay'),
style: TextStyle(
color: Colors.white, fontSize: 20),
)),
class PhoneAuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState>
final UserRepository _userRepository;
PhoneAuthenticationBloc(@required UserRepository userRepository)
: assert(userRepository != null),
_userRepository = userRepository;
String verificationId = "";
@override
AuthenticationState get initialState => Uninitialized();
@override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event) async*
// phone verification
if (event is VerifyPhoneNumberEvent)
print('VerifyPhoneNumberEvent received');
yield* _mapVerifyPhoneNumberToState(event);
else if (event is PhoneCodeSentEvent)
print('PhoneCodeSentEvent received');
yield OtpSentState();
else if (event is VerificationCompletedEvent)
print('VerificationCompletedEvent received');
yield VerificationCompleteState(firebaseUser: event.firebaseUser, isVerified: event.isVerified);
else if (event is VerificationExceptionEvent)
print('VerificationExceptionEvent received');
yield VerificationExceptionState(message: event.message);
else if (event is VerifySmsCodeEvent)
print('VerifySmsCodeEvent received');
yield VerifyingState();
try
AuthResult result =
await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode);
if (result.user != null)
yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
else
yield OtpExceptionState(message: "Invalid otp!",verificationId: verificationId);
catch (e)
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
print(e);
else if ( event is PhoneCodeAutoRetrievalTimeoutEvent)
yield PhoneCodeAutoRetrievalTimeoutState(verificationId: event.verificationId);
if(event is SendVerificationCodeEvent)
yield*_mapVerificationCodeToState(event);
Stream<AuthenticationState> _mapVerifyPhoneNumberToState(VerifyPhoneNumberEvent event) async*
print('_mapVerifyPhoneNumberToState V2 started');
yield VerifyingState();
final phoneVerificationCompleted = (AuthCredential authCredential)
print('_mapVerifyPhoneNumberToState PhoneVerificationCompleted');
// _userRepository.getUser();
_userRepository.getCurrentUser().catchError((onError)
print(onError);
).then((user)
add(VerificationCompletedEvent(firebaseUser: user, isVerified: true));
);
;
final phoneVerificationFailed = (AuthException authException)
print('_mapVerifyPhoneNumberToState PhoneVerificationFailed');
print(authException.message);
add(VerificationExceptionEvent(onError.toString()));
;
final phoneCodeSent = (String verificationId, [int forceResent])
print('_mapVerifyPhoneNumberToState PhoneCodeSent');
this.verificationId = verificationId;
add(PhoneCodeSentEvent());
;
final phoneCodeAutoRetrievalTimeout = (String verificationId)
// after this print Bloc error is Bad state: Cannot add new events after calling close
print('_mapVerifyPhoneNumberToState PhoneCodeAutoRetrievalTimeout');
this.verificationId = verificationId;
add(PhoneCodeAutoRetrievalTimeoutEvent(verificationId: verificationId));
;
await _userRepository.verifyPhone(
phoneNumber: event.phoneNumber,
timeOut: Duration(seconds: 0),
phoneVerificationFailed: phoneVerificationFailed,
phoneVerificationCompleted: phoneVerificationCompleted,
phoneCodeSent: phoneCodeSent,
autoRetrievalTimeout: phoneCodeAutoRetrievalTimeout);
Stream<AuthenticationState> _mapVerificationCodeToState(SendVerificationCodeEvent event) async*
print('_mapVerificationCodeToState started');
yield VerifyingState();
try
AuthResult result =
await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode);
if (result.user != null)
yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
else
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
catch (e)
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
print(e);
【问题讨论】:
你在哪里打电话BlocProvider.of<PhoneAuthenticationBloc>
@PietervanLoon 在onPressed
回调上的按钮中,我执行检查,如果失败,我返回一个带有onPressed
的按钮的Dialog
我发送事件。抱歉,我没有意识到缺少一些代码示例,感谢您让我注意到它。
【参考方案1】:
您在添加事件时使用了错误的上下文。 显示对话框时,小部件将放置在 bloc 提供程序上方的叠加层中,因此通过使用对话框的上下文,您无法找到 bloc,因为它上面没有提供程序。
要将此名称固定为对话框的上下文(即dialogContext),以便在执行BlocProvider.of(context)
时,上下文指的是显示对话框的小部件的上下文,而不是对话框本身的上下文。
【讨论】:
绝对!你确实是对的..我自己看不到。非常感谢,欢迎来到 ***。好的开始。干杯。以上是关于使用不包含 PhoneAuthenticationBloc 类型的 Bloc 的上下文调用 BlocProvider.of()。扑的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中使用 WinSCP 传输仅包含数字而不包含字母的文件?