【问题标题】:Dart Provider: not available at the immediate child飞镖提供者:直系子女不可用
【发布时间】:2020-04-30 13:52:33
【问题描述】:
  @override
  Widget build(BuildContext context) {
    return BlocProvider<HomeBloc>(
        create: (context) {
          return HomeBloc(homeRepo: HomeRepository());
        },
        child: BlocProvider.of<HomeBloc>(context).state is HomeStateLoading
            ? CircularProgressIndicator()
            : Container());
  }

我对错误感到困惑:

BlocProvider.of() called with a context that does not contain a Bloc of type HomeBloc.
No ancestor could be found starting from the context that was passed to
BlocProvider.of<HomeBloc>().

我不是刚刚在其直接父级创建了HomeBloc 吗?它想要什么?

【问题讨论】:

    标签: flutter dart provider bloc


    【解决方案1】:

    您正在使用传递给小部件类的build 方法的context 来查找父BlocProvider。但是,就您的小部件类而言,该上下文是小部件树。因此,您的BlocProvider.of 正在寻找一个BlocProvider,它是您的widget 类 的父级。如果要获取作为直接父级的提供程序,则需要一个新的context 对象,其中BlocProvider 是小部件树中的祖先。最简单的方法是使用Builder 小部件:

    @override
    Widget build(BuildContext context) {
      return BlocProvider<HomeBloc>(
        create: (context) {
          return HomeBloc(homeRepo: HomeRepository());
        },
        child: Builder(
          builder: (newContext) => BlocProvider.of<HomeBloc>(newContext).state is HomeStateLoading
              ? CircularProgressIndicator()
              : Container(),
        ),
      );
    }
    

    话虽如此,创建提供者然后立即尊重提供者是非常多余的。提供者用于在小部件树的下方检索内容,通常不用于直接后代。在这种情况下,使用提供程序是多余的,实际上没有任何理由不将 bloc 作为您的类的一个字段并直接引用它。

    【讨论】:

    • 谢谢你。但我仍然不能完全同意 Provider 所做/定义的事情。显然BlocProvider.of()child: 中被调用。它怎么不在它的小部件树中?她是在骗我这是我的孩子???
    • @nigong 它与调用BlocProvider.of() 的位置无关,也与您传递给它的上下文对象有关。您正在传递来自父小部件类的context(我们称之为Foo)。没有BlocProviderFoo 的祖先,所以就context 而言,BlocProvider 不存在。这就是为什么您需要Builder 来获得一个确实 具有BlocProvider 作为祖先的 上下文对象newContext
    【解决方案2】:

    来自documentation

    读取值最简单的方法是使用静态方法 Provider.of(BuildContext 上下文)。

    此方法将从小部件开始在小部件树中查找 与传递的 BuildContext 关联,它将返回最近的 找到 T 类型的变量(如果没有找到,则抛出)。

    在您的情况下,它开始从您的整个小部件(与 BuildContext 关联)中查找小部件树。

    因此,您需要将您的 BlocProvider 移动为该小部件的祖先。

    如果由于某种原因这不可能,您可以使用Consumer,当您没有作为所述提供者的后代的BuildContext 时,它允许从提供者获取值。

    阅读https://pub.dev/documentation/provider/latest/provider/Consumer-class.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-12
      • 2020-05-16
      • 2021-10-01
      • 2022-01-23
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多