【问题标题】:Bloc isn't found in the widget tree在小部件树中找不到 Bloc
【发布时间】:2021-01-12 17:45:18
【问题描述】:

因为代码比较大,我试着用文字总结一下。

这是最新的例外:

Error: Could not find the correct Provider<ProdEntriesSearchCubit> above this BlocListener<ProdEntriesSearchCubit, ProdEntriesSearchState> Widget

This likely happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:

- The provider you are trying to read is in a different route.

  Providers are "scoped". So if you insert of provider inside a route, then
  other routes will not be able to access that provider.

- You used a `BuildContext` that is an ancestor of the provider you are trying to read.

  Make sure that BlocListener<ProdEntriesSearchCubit, ProdEntriesSearchState> is under your MultiProvider/Provider<ProdEntriesSearchCubit>.
  This usually happens when you are creating a provider and trying to read it immediately.

在屏幕 1 中,我有以下构建方法:

    Widget build(BuildContext context) {
        final entriesState = context.watch<ProdEntriesCubit>().state;
        return BlocProvider(
          create: (context) => ProdEntriesSearchCubit(
            productsRepository: context.watch<ProductsRepository>(),
          ),
          child: Builder(
            builder: (context) => SafeScreen(
              child: Scaffold(
                body: _buildBody(context, entriesState: entriesState),
                floatingActionButton: _buildFab(context),
              ),
            ),
          ),
        );
      }

_buildFab(BuildContext context) {
    return FloatingActionButton(
      child: Icon(
        Icons.add,
        color: Colors.white,
      ),
      onPressed: () async {
        await navigatorPush(context, screen: AdminProdEntryScreen());
      },
    );
  }

在 AdminProdEntryScreen 我再做一次:

navigatorPush(
          context,
          screen: EntryProdSearchScreen(),
        );

在 EntryProdSearchScreen 我从上面得到错误。

为什么在小部件树中找不到 BloC/Cubit?

我什至使用了多个 Builder 小部件,但我总是遇到这个异常。

【问题讨论】:

    标签: flutter-provider flutter-bloc


    【解决方案1】:

    当您提供 BLoC 时,它可以访问当前的小部件树,当您导航到另一个屏幕时,它将无法访问该 BLoC。 您可以通过以下两种方式之一解决此问题。

    1
    您可以使用 bloc (Multi) 提供程序包装整个应用程序,无论导航如何,您都可以访问该 bloc。
    之所以可行,是因为您使用 bloc 提供程序将导航包装在 MaterialApp 中。

      runApp(
        MultiBlocProvider(
          providers: [
            BlocProvider<ProdEntriesSearchCubit>(
              create: (context) => ProdEntriesSearchCubit(),
            ),
          ],
          child: MyApp(),
        ),
      );
    

    2
    您可以通过 nav 路由传递 bloc 的实例,并使用 BlocProvider.value 提供 same 的 bloc 实例。

    
    //nav method
    Navigator.of(context).pushNamed(
      '/entry_prod_search_screen',
      arguments: context.read< ProdEntriesSearchCubit >(),
    );
    
    //in the navigated route screen
    final bloc = ModalRoute.of(context).settings.arguments;
    
    return MultiBlocProvider(
      providers: [
        BlocProvider.value(
          value: bloc,
        ),
      ],
      child: ...,
    );
    

    【讨论】:

    • 谢谢。我想避免使整个应用程序都可以使用该 bloc,如果不使用该 bloc,您是否知道资源是否关闭?
    • 当你说资源时,你是什么意思?你是指集团本身、对话、屏幕吗? bloc 的实例仍然可用,直到提供它的屏幕被关闭。
    • 我的意思是,在关闭使用它们的屏幕后,如果 bloc 的实例仍然在后台运行(使用 RAM/CPU)。
    • 如果最初使用BlocProvider 提供bloc 实例的屏幕被关闭,那么bloc 将不再运行。如果您希望它在后台运行,则需要使用 bloc 提供程序包装您的应用程序以始终访问它
    • 我担心是这种情况,感谢您为我解决问题。祝你有美好的一天!
    猜你喜欢
    • 1970-01-01
    • 2019-12-10
    • 2021-07-29
    • 1970-01-01
    • 2021-12-05
    • 2021-11-15
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    相关资源
    最近更新 更多