gpt4 book ai didi

flutter - Flutter-使用MultiBlocProvider但无法在子屏幕上呈现BlocListener

转载 作者:行者123 更新时间:2023-12-03 04:52:25 27 4
gpt4 key购买 nike

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

  • 我在声明了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库的文档中:

    You cannot access a bloc from the same context in which it was provided so you must ensure BlocProvider.of() is called within a child BuildContext



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

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

    关于flutter - Flutter-使用MultiBlocProvider但无法在子屏幕上呈现BlocListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61167508/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com