Dart 提供者:直接子对象不可用

Dart Provider: not available at the immediate child

  @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 吗?它想要什么?

您正在使用传递给小部件 class 的 build 方法的 context 来查找父级 BlocProvider。但是,就您的小部件 class 而言,该上下文是小部件树。因此,您的 BlocProvider.of 正在寻找一个 BlocProvider,它是您的 小部件 class 的父级。如果你想获得作为直接父级的提供者,你需要一个新的 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 成为您的 class 的字段并直接引用它。

来自documentation :

The easiest way to read a value is by using the static method Provider.of(BuildContext context).

This method will look up in the widget tree starting from the widget associated with the BuildContext passed and it will return the nearest variable of type T found (or throw if nothing is found).

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

所以您需要移动您的 BlocProvider 成为此小部件的祖先。

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

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