导航到不同路线后,Flutter 找不到正确的 Provider<Bloc>

Posted

技术标签:

【中文标题】导航到不同路线后,Flutter 找不到正确的 Provider<Bloc>【英文标题】:Flutter could not find the correct Provider<Bloc> after navigating to different route 【发布时间】:2021-07-25 03:05:03 【问题描述】:

我正在使用 bloc 来处理注册表单的状态。但我得到了错误: Error: Could not find the correct Provider&lt;CreateDidBloc&gt; above this BlocBuilder&lt;CreateDidBloc, CreateDidState&gt; Widget. 正如您在错误中看到的那样,我确实使用了 bloc CreateDidBloc 和状态 CreateDidState 并通过 BlocBuilder 获取它们。 BlocBuilder 位于我的“注册”页面中,在我的例子中称为Creation。当我从介绍页面导航到创建页面时出现错误。 下面是我的MaterialApp 的摘录,其中我用RepositoryProviderBlocProvider 包装了创建页面,以便创建页面可以访问Bloc 和存储库。但是由于某种原因,creation 页面在导航到创建页面后没有找到CreateDidBloc 的 BlocProvider。

initialRoute: "/introduction",
routes: 
  "/introduction": (context) => Introduction(),
  "/create": (context) => RepositoryProvider(
        create: (context) => CreateDidRepository(),
        child: BlocProvider(
          create: (BuildContext context) => CreateDidBloc(
            repo: context.read<CreateDidRepository>(),
          ),
          child: Creation(),
        ),
      ),
,

这就是我导航到Creation 屏幕的方式:

Navigator.push(context,
    PageTransition(type: PageTransitionType.fade, child: Creation()));

创建(注册)页面:

@override
Widget build(BuildContext context) 
  return SafeArea(
      child: Scaffold(
          body: Column(
    children: [
      Expanded(
        child: PageView(
          physics: const NeverScrollableScrollPhysics(),
          controller: _pageController,
          onPageChanged: (index) 
            setState(() => currentStep = index);
          ,
          children: [
            Step1(),
            Step2(),
            Step3(),
          ],
        ),
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          BlocBuilder<CreateDidBloc, CreateDidState>(
            builder: (context, state) 
              return ElevatedButton(
                  onPressed: () 
                    next();
                  ,
                  child: Text(L.of(context).next));
            ,
          ),
          BlocBuilder<CreateDidBloc, CreateDidState>(
            builder: (context, state) 
              return OutlinedButton(
                  onPressed:
                      state.formStatus is FormSubmitting ? null : cancel,
                  child: Text(L.of(context).back));
            ,
          )
        ],
      ),
      const SizedBox(
        height: 16,
      )
    ],
  )));

这是堆栈跟踪:

When the exception was thrown, this was the stack
#0      Provider._inheritedElementOf
#1      Provider.of
#2      ReadContext.read
#3      _BlocBuilderBaseState.initState
#4      StatefulElement._firstBuild

【问题讨论】:

【参考方案1】:

我找到了 BlocBuilder 导航后找不到 CreateDidBloc 的原因。发生该错误是因为在 Flutter 中导航会将您的页面推送到小部件树中 MaterialApp 的正下方。这意味着我新导航的页面位于 MaterialApp 下方的小部件树中指定的 BlocProvider 之上。 为了解决这个问题,我只是用 MultiBlocProvider 和 RepositoryProvider 包装了我的 MaterialApp,这样无论我在哪条路线上,都可以全局提供 Bloc。 这是我可以在其中全局定义集团的重要摘录:

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return RepositoryProvider(
        create: (context) => CreateDidRepository(),
        child: MultiBlocProvider(
            providers: [
              BlocProvider<LanguageBloc>(
                  create: (context) =>
                      LanguageBloc(LanguagePreference.getLanguage())),
              BlocProvider<CreateDidBloc>(
                  create: (context) =>
                      CreateDidBloc(repo: context.read<CreateDidRepository>()))
            ],
            child: BlocBuilder<LanguageBloc, LanguageState>(
              builder: (context, state) 
                return MaterialApp(...)

【讨论】:

以上是关于导航到不同路线后,Flutter 找不到正确的 Provider<Bloc>的主要内容,如果未能解决你的问题,请参考以下文章

角度导航到具有不同参数的相同路线

Flutter 错误:找不到正确的 ScopedModel

TypeError:在导航状态中找不到“路线”

Flutter导航到新页面时抛出错误

Flutter - Provider 变量更改时触发导航

Aurelia:找不到路线的名称