无法在此应用程序小部件上方找到正确的提供者<TokenBloc>

Could not find the correct Provider<TokenBloc> above this App Widget

我使用 BLoC。如何正确创建它,不会出现由于缺少小部件树下的小部件而不会出现的情况。现在我通常是这样的:

    Widget build(BuildContext context) {
return MaterialApp(
    // debugShowCheckedModeBanner: false,
    theme: Styles.appTheme,

    home: BlocProvider<TokenBloc>(
      create: (context) => di.sl<TokenBloc>(),
      child: _childTokenBloc,
    ),
  );
}


   

 Widget get _childTokenBloc {
      return BlocBuilder<TokenBloc, TokenState>(builder: (context, state) {
        if (state is TokenInitialState) {
          context.read<TokenBloc>().add(TokenCheckEvent());
          return const LogoImage();
        }
        if (state is TokenCheckState) {
          return const LogoImage();
        }
    
        if (state is TokenOkState) {
          return MainPageWidget();
        }
    
        if (state is TokenNoAuthorizationState) {
          return const AuthorizationPageWidget();
        }
        return const LogoImage();
      }
      );
    }

在 AuthorizationPageWidget 中我这样做:

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const ConfirmAuthorizationPage()),
);

我尝试从 ConfirmAuthorizationPage 转向 TokenBloc:

context.read<TokenBloc>().add(TokenAddEvent());

但我收到错误:在此应用小部件上方找不到正确的提供程序

我以为TokenBloc 会在widget 树中找到,但不是吗?以及如何解决这个问题?需要在 ConfirmAuthorizationPage 小部件的构建方法中使用 MultiBlocProvider 吗?会重新初始化,之前的就不用了


更新 1: 代码 AuthorizationPageWidget:

class AuthorizationPageWidget extends StatefulWidget {
  const AuthorizationPageWidget({Key? key}) : super(key: key);

  @override
  _AuthorizationPageWidgetState createState() =>
      _AuthorizationPageWidgetState();
}

class _AuthorizationPageWidgetState extends State<AuthorizationPageWidget> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider<AuthorizationBloc>(
        create: (context) => sl<AuthorizationBloc>(),
        child: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _title,
                _description,
                Expanded(child: Align(alignment: FractionalOffset.bottomCenter, child: _bottomButton))
              ],
            ),
        ),
      ),
    );
  }


//......   

 
void pushConfirmPage(String number) {

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => ConfirmAuthorizationPage(number: number,)),
    );
  }
}

如果你想在你所有的应用程序中提供你的 Bloc,你必须像这样在你的 MaterialApp 中写它,而不是在正文中;

return 
    BlocProvider<TokenBloc>( // like this
       create: (context) => TokenBloc(),
       child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter Demo',
          home: _TokenHome(),
       ),
    ),
);

class _TokenHome extends StatelessWidget { // use a class instead of function
  const _TokenHome({
    Key? key,
  }) : super(key: key);

@override
  Widget build(BuildContext context) {
    return BlocBuilder<TokenBloc, TokenState>(
      builder: (context, state) {
          if (state is TokenInitialState) {
            context.read<TokenBloc>().add(TokenCheckEvent());
            return const LogoImage();
          }
          if (state is TokenCheckState) {
            return const LogoImage();
          }
          if (state is TokenOkState) {
            return MainPageWidget();
          }
          if (state is TokenNoAuthorizationState) {
            return const AuthorizationPageWidget();
          }
          return Container(
            width: 50,
            height: 50,
            color: Colors.red,
          ); // use this if there is not a state
        }
    );
  }
}

如果由于某种原因它不再显示任何内容,那是因为你的某些 类 像 AuthorizationPageWidget 或 LogoImage 是错误的,检查一下。

-------- 编辑

在每个页面上使用 BlocProvider 可能很有用,但请记住,例如 AuthorizationBloc 仅适用于其子页面,如果你在屏幕的另一边调用它不会起作用,所以强烈建议在 MaterialApp 中使用 MultiBlocProvider 以避免将来出现问题;

return MultiBlocProvider( // like this
  providers: [
    BlocProvider<TokenBloc>(
      create: (context) => TokenBloc(),
    ),
    BlocProvider<AuthorizationBloc>(
      create: (context) => AuthorizationBloc(),
    ),
  ],
  child: BlocBuilder<LanguageCubit, Locale?>(
    builder: (context, lang) {
      return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
      );
    },
  ),
);

所以你用来创建的所有其他 BlocProvider,删除它们,你不需要它们,现在如果你使用 BlocBuilder, 任何 Bloc 的 BlocListeners,您不会有任何不便。