使用不包含 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&lt;PhoneAuthenticationBloc&gt; @PietervanLoon 在onPressed 回调上的按钮中,我执行检查,如果失败,我返回一个带有onPressed 的按钮的Dialog 我发送事件。抱歉,我没有意识到缺少一些代码示例,感谢您让我注意到它。 【参考方案1】:

您在添加事件时使用了错误的上下文。 显示对话框时,小部件将放置在 bloc 提供程序上方的叠加层中,因此通过使用对话框的上下文,您无法找到 bloc,因为它上面没有提供程序。

要将此名称固定为对话框的上下文(即dialogContext),以便在执行BlocProvider.of(context) 时,上下文指的是显示对话框的小部件的上下文,而不是对话框本身的上下文。

【讨论】:

绝对!你确实是对的..我自己看不到。非常感谢,欢迎来到 ***。好的开始。干杯。

以上是关于使用不包含 PhoneAuthenticationBloc 类型的 Bloc 的上下文调用 BlocProvider.of()。扑的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 验证字符串不包含 HTML

在 C# 中使用 WinSCP 传输仅包含数字而不包含字母的文件?

使用 Capacitor Plugins 作为脚本包含(不使用包/模块加载器)

为啥我不应该包含 cpp 文件而使用标头?

使用 XSLT 过滤不包含节点的 XYZ

为啥mac不需要包含智能指针? [复制]