导航颤动后的家长集团无法实现

发布于 2025-01-28 19:34:34 字数 1868 浏览 5 评论 0原文

我已经在homepage中创建了cubit surveyscubit blocprovider 组件,现在,我想从在其子弹中推动的新页面访问它。

所有操作都很好,直到在此处达到按下页面,显示以下错误告诉我,在上一页上找不到surveysbloc

BlocProvider.of() called with a context that does not contain a SurveysCubit.

这是主页:

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
  create: (_) =>
      SurveysCubit(repo: RepositoryProvider.of<SurveyRepository>(_)),
  child: Builder(builder: (newContext) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.push(
                newContext,
                MaterialPageRoute<void>(
                  builder: (BuildContext newContext) => Surveys(),
                ),
              ),
              child: const Text("Surveys"),
            ),
          ],
        ),
      ),
    );
  }),
);
  }
}

surveys ,推送页面:

class Surveys extends StatelessWidget {
  List<Survey> surveys = [];
  Surveys({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    surveys = BlocProvider.of<SurveysCubit>(context).getSurveys; //this call fails
    return Scaffold(
      body: ListView.builder(
        itemCount: surveys.length,
        itemBuilder: (context, i) => Column(
          children: [
            ShowSurvey(survey: surveys[i]),
            SizedBox(
              height: 20,
            ),
          ],
        ),
      ),
    );
  }
}

我知道我可以避免构建器小部件,但我想强制一个新的上下文创建。我认为我提供了正确的上下文,因此它应该起作用,我不明白发生了什么。

I have created the Cubit SurveysCubit in HomePage from BlocProvider component, now, I want to access it from a new page pushed in its child body.

All works fine until the pushed page is reached here the following error is shown telling me that the SurveysBloc created on the previous page is not found :

BlocProvider.of() called with a context that does not contain a SurveysCubit.

This is the home page :

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
  create: (_) =>
      SurveysCubit(repo: RepositoryProvider.of<SurveyRepository>(_)),
  child: Builder(builder: (newContext) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.push(
                newContext,
                MaterialPageRoute<void>(
                  builder: (BuildContext newContext) => Surveys(),
                ),
              ),
              child: const Text("Surveys"),
            ),
          ],
        ),
      ),
    );
  }),
);
  }
}

Surveys, the pushed page :

class Surveys extends StatelessWidget {
  List<Survey> surveys = [];
  Surveys({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    surveys = BlocProvider.of<SurveysCubit>(context).getSurveys; //this call fails
    return Scaffold(
      body: ListView.builder(
        itemCount: surveys.length,
        itemBuilder: (context, i) => Column(
          children: [
            ShowSurvey(survey: surveys[i]),
            SizedBox(
              height: 20,
            ),
          ],
        ),
      ),
    );
  }
}

I know I could avoid Builder widget, but I wanted to force a new context creation. I think I provided the right context, so it should work, I don't understand what's happening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聊慰 2025-02-04 19:34:34

您想在2页之间分享您的cubit状态。您有2个选项可以实现这一目标,但首先让我解释什么blocprovider.of或navigator。
clasta.of意味着让我的祖先在上下文树中搜索类型的对象。
因此,当您键入Navigator.时,您会从树上上方的节点中获取Navigator对象,与BlocProvider.of相同。
现在回到您的问题,您在页面主页中提供了一个集团,然后尝试从调查页面访问它,现在此调查页面无法访问它,因为您要求获得的集团在调查的祖先节点页面中没有提供。 。
要解决此问题,您可以将BLOC实例作为参数传递以调查页面并用BlocProvider.Value包装孔页面,

class Surveys extends StatelessWidget {
  final cubit;
  Surveys({Key? key, required this.cubit}) : super(key: key);

  @override
  Widget build(BuildContext context) {
   return BlocProvider.value(
          value: cubit,
          child:....
          );
  }
}

或者在推动推销时直接包装页面(我不建议您使用此页面,因为每次您想使用此页面时,您都有要记住将其包裹在Bloc提供商中)

Navigator.push(
                newContext,
                MaterialPageRoute<void>(
                  builder: (BuildContext newContext) => BlocProvider.value(
                  value: BlocProvider.of<SurveysCubit>(newContext);
                  child: Surveys()
                  ),
                ),
              ),

或最后一个选项是您要在每个页面中访问Bloc时,不仅这2页只需用Bloc提供商将您的材料应用程序包装在主函数中。
现在,每当您致电blocprovider.of(上下文)时,您都会得到它。

you want to share your cubit state between 2 pages you have 2 option to achieve that but first let me explain what BlocProvider.of or Navigator.of basically the "of" word,
ClassA.of means that lets search in my ancestors in context tree about an object of type ClassA.
so when you are typing Navigator.of you are getting the Navigator object from node above you in the tree, same as BlocProvider.of.
now back to your question you are providing a bloc in page HomePage, then trying to access it from Surveys page, now this Surveys page can not access it, because the bloc you are asking to get is not providing in an ancestor node of Surveys page.
to solve this you can pass the bloc instance as parameter to surveys page and wrap the hole page with BlocProvider.value

class Surveys extends StatelessWidget {
  final cubit;
  Surveys({Key? key, required this.cubit}) : super(key: key);

  @override
  Widget build(BuildContext context) {
   return BlocProvider.value(
          value: cubit,
          child:....
          );
  }
}

or wrap the page directly when you are pushing it (I do not recommend this because every time you want to use this page you have to remember to wrap it with bloc provider)

Navigator.push(
                newContext,
                MaterialPageRoute<void>(
                  builder: (BuildContext newContext) => BlocProvider.value(
                  value: BlocProvider.of<SurveysCubit>(newContext);
                  child: Surveys()
                  ),
                ),
              ),

or last Option is when you want to access you bloc in every page not only this 2 pages just wrap your MaterialApp in the main function with bloc provider.
now when ever you call BlocProvider.of(context) you will get it.

冷夜 2025-02-04 19:34:34

首先,如果您的主页正在使用SurveyScubit我建议将其完全包装,而不是在build> build>的顶部声明blocprovider代码>方法。这将最大程度地减少您遇到此类问题的机会。

但是,如果您会坚持实施,我有几个提示。

  • 从树上删除建筑商;它是定义nocelesswidget的内联替代方案。这里是多余的。
  • 即使按下调查页面时,您将通过正确的上下文,因为repositoryProvider使用new throwaway 上下文上下文 _ 代码>显然没有存储库,或者它将是您的实现,而您的实现却误导了阅读它的人。
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (newContext) => SurveysCubit(
        repo: RepositoryProvider.of<SurveyRepository>(newContext),
      ),
      child: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => Navigator.push(
                  newContext,
                  MaterialPageRoute<Surveys>(
                    builder: (_) => Surveys(),
                  ),
                ),
                child: const Text("Surveys"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

如果这无济于事,则可能需要使用blocprovicer.value()包装

其次,我通过在您的survey> survey页面中使用blocbuilder使用BLOC的力量建议,而不是一次读取Cubit值。您一次通过一次数据而失去对状态变化的响应能力。您想对更改做出反应的最佳情况,而不是重新加载页面以获取更改等。

请考虑以下内容:

class Surveys extends StatelessWidget {
  Surveys({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<SurveysCubit, SurveysState>(
        builder: (context, state) {
          return ListView.builder(
            itemCount: state.surveys.length,
            itemBuilder: (context, i) => Column(
              children: [
                ShowSurvey(survey: state.surveys[i]),
                const SizedBox(height: 20),
              ],
            ),
          );
        },
      ),
    );
  }
}

请确定它是否有效。

First of, if your HomePage is using SurveysCubit I'd recommend wraping it completely rather than declaring BlocProvider on top of build method. This will minimalize chance that you will run into issues like this one.

But if you wonna stay with your implementation, I have few tips.

  • Remove Builder from tree; it is an inline alternative to defining StatelessWidget. It's redundant here.
  • Even if you will pass the right context when pushing Surveys page, errors might occur because RepositoryProvider is using new throwaway context _ that clearly doesnt have repo in it, or it will but then, your implementation is missleading to people reading it.
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (newContext) => SurveysCubit(
        repo: RepositoryProvider.of<SurveyRepository>(newContext),
      ),
      child: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => Navigator.push(
                  newContext,
                  MaterialPageRoute<Surveys>(
                    builder: (_) => Surveys(),
                  ),
                ),
                child: const Text("Surveys"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

If this doesnt help, you might need to wrap MaterialPageRoute with BlocProvicer.value().

Secondly, I advice using power of bloc by using BlocBuilder inside your Survey page rather than reading cubit value once. You lose app responsiveness to state changes by fething data once. Best case scenario you want to react to changes, not reload page to get changes etc.

Consider this:

class Surveys extends StatelessWidget {
  Surveys({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<SurveysCubit, SurveysState>(
        builder: (context, state) {
          return ListView.builder(
            itemCount: state.surveys.length,
            itemBuilder: (context, i) => Column(
              children: [
                ShowSurvey(survey: state.surveys[i]),
                const SizedBox(height: 20),
              ],
            ),
          );
        },
      ),
    );
  }
}

Please tell if it worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文