我将描述我的问题和遇到的错误。然后,我将复制代码以使其更加清晰。问题为:

  • 我在声明了2个bloc的根窗口小部件(StartupScreen)上使用MultiBlocProvider
    AuthenticationBloc,ApplicationBloc。
  • 在根窗口小部件(StartupScreen)上使用BlocListener<AuthenticationBloc, AuthenticationState>
  • 如果AuthenticationBloc的状态更改为AuthAuthenticatedState,则路由到MainScreen,否则路由到LoginScreen。
  • 如果用户已进入,则路由到MainScreen:
  • 我将(异步地)从存储中获取currentUser,然后将BlocListener封装在内部FutureBuilder中。最终导致无法显示屏幕并出现以下错误:
  • BlocProvider.of() called with a context that does not contain a Bloc of type ApplicationBloc.
    
    No ancestor could be found starting from the context that was passed to BlocProvider.of<ApplicationBloc>().
    
    This can happen if the context you used comes from a widget above the BlocProvider.
    
    The context used was: BlocListener<ApplicationBloc, ApplicationState>(dirty, state: _BlocListenerBaseState<ApplicationBloc, ApplicationState>#1abf7(lifecycle state: created))
    
    The relevant error-causing widget was
        FutureBuilder<UserCredentials>                       package:my_app/…/ui/main_screen.dart:43
    
    When the exception was thrown, this was the stack
    #0      BlocProvider.of                                  package:flutter_bloc/src/bloc_provider.dart:106
    #1      _BlocListenerBaseState.initState                 package:flutter_bloc/src/bloc_listener.dart:160
    #2      StatefulElement._firstBuild                      package:flutter/…/widgets/framework.dart:4355
    #3      ComponentElement.mount                           package:flutter/…/widgets/framework.dart:4201
    #4      SingleChildWidgetElementMixin.mount              package:nested/nested.dart:223
    ...
    

    StartupScreen.dart
    class StartupScreen extends StatelessWidget {
      final ApplicationBloc appBloc;
      final AuthenticationBloc authBloc;
    
      StartupScreen(this.appBloc, this.authBloc) : super();
    
      @override
      Widget build(BuildContext context) {
        ScreenSizeConfig().init(context);
        authBloc.add(AuthStartedEvent());
    
        return MultiBlocProvider(
          providers: [
            BlocProvider<ApplicationBloc>(
              create: (context) => appBloc,
            ),
            BlocProvider<AuthenticationBloc>(
              create: (context) => authBloc,
            ),
          ],
          child: BlocListener<AuthenticationBloc, AuthenticationState>(
            listener: (context, state) {
              if (state is AuthUnauthenticatedState) {
                Navigator.of(context).pushReplacementNamed(RouteConstants.LOGIN_SCREEN);
              } else if (state is AuthAuthenticatedState) {
                Navigator.of(context).pushReplacementNamed(RouteConstants.MAIN_SCREEN);
              }
            },
            child: BlocBuilder<AuthenticationBloc, AuthenticationState>(
              builder: (context, state) {
                return Center(
                  child: Container(
                    child: Text('Startup Screen'),
                  ),
                );
              },
            ),
          ),
        );
      }
    }
    

    MainScreen.dart
    class MainScreen extends StatelessWidget {
      final ApplicationBloc appBloc;
      final AuthenticationBloc authBloc;
    
      MainScreen(this.appBloc, this.authBloc) : super();
    
      @override
      Widget build(BuildContext context) {
        return _MainPageWidget(appBloc, authBloc);
      }
    }
    
    class _MainPageWidget extends StatefulWidget {
      final ApplicationBlocappBloc;
      final AuthenticationBloc authBloc;
    
      _MainPageWidget(this.appBloc, this.authBloc) : super();
    
      @override
      State<StatefulWidget> createState() => _MainPageState();
    }
    
    class _MainPageState extends State<_MainPageWidget> {
      Future<UserCredentials> getUserCredentials() async {
        return await widget.appBloc.authService.getUser();
      }
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<UserCredentials>(
            future: getUserCredentials(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else {
                return _buildBlocListener(snapshot.data);
              }
            });
      }
    
      Widget _buildBlocListener(UserCredentials userCredentials) {
        return BlocListener<ApplicationBloc, ApplicationState>(
          listener: (context, state) {
            if (userCredentials.isNewUser) {
              widget.appBloc.add(AppNewUserEvent());
            } else {
              widget.appBloc
                  .add(AppAlreadyCompletedNewUserProcessEvent());
            }
          },
          child: _buildBlocBuilder(context, widget.appBloc),
        );
      }
    
      Widget _buildBlocBuilder(BuildContext context, ApplicationBloc appBloc) {
        return BlocBuilder<ApplicationBloc, ApplicationState>(
          builder: (context, state) {
            print('main_screen.dart: go to mainscreen BlocBuilder builder: state: $state');
            return Container(
              child: Text('Main Screen'),
            );
          },
        );
      }
    }
    
    

    最佳答案

    从bloc库的文档中:



    https://bloclibrary.dev/#/faqs?id=blocproviderof-fails-to-find-bloc

    您将必须取出BlocListener并将其放在单独的小部件中,或者将BlocListener与构建器小部件包装在一起。

    08-18 19:45